From a72aa21a2f1bdaccabc757b0c8ecef17959785fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 1 Aug 2024 16:11:44 +0800 Subject: =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99=E7=A9=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/core/fix-indent.lua | 138 +++++++--------------------- script/core/type-formatting.lua | 195 +--------------------------------------- 2 files changed, 36 insertions(+), 297 deletions(-) diff --git a/script/core/fix-indent.lua b/script/core/fix-indent.lua index 9389072d..2d1dc318 100644 --- a/script/core/fix-indent.lua +++ b/script/core/fix-indent.lua @@ -4,95 +4,44 @@ local lookBackward = require 'core.look-backward' local proto = require 'proto.proto' ---@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 +---@param change table +---@param edits table[] +local function removeSpacesAfterEnter(state, change, edits) + if not change.text:match '^\r?\n[\t ]+\r?\n' 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) - 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 - end - end - return nil -end + local text = state.originText or state.lua + ---@cast text -? ----@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 - end - local offset = guide.positionToOffsetByLines(lines, position) - local lastOffset = lookBackward.findAnyOffset(text, offset) - if not lastOffset then - return nil - end - for _, symbol in ipairs { ... } do - if text:sub(lastOffset - #symbol + 1, lastOffset) == symbol then - return guide.offsetToPositionByLines(lines, lastOffset) + -- 清除前置空格 + 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 ----@param change table ----@param result any[] -local function checkSplitOneLine(state, change, result) - if change.text ~= '\r\n' - and change.text ~= '\n' then - return + if leftOffset and leftOffset < startOffset then + edits[#edits+1] = { + start = leftOffset, + finish = startOffset, + text = '', + } 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 - return - end - local bPosition = findBackward(state, 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(state, bPosition, edits) - for _, edit in ipairs(edits) do - result[#result+1] = edit + -- 清除后置空格 + local endOffset = startOffset + #change.text + local _, rightOffset = text:find('^[\t ]+', endOffset + 1) + if rightOffset then + edits[#edits+1] = { + start = endOffset, + finish = rightOffset, + text = '', + } end end @@ -129,41 +78,22 @@ 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) - end + local firstChange = changes[1] + if firstChange.range then + removeSpacesAfterEnter(state, firstChange, edits) end applyEdits(state, edits) 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 -- cgit v1.2.3 From 1c7755b317d1e811a3f71f3ec745800555575fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 1 Aug 2024 16:19:34 +0800 Subject: =?UTF-8?q?=E5=88=A0=E6=8E=89=E6=B2=A1=E7=94=A8=E7=9A=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.lua | 1 - test/type_formatting/init.lua | 209 ------------------------------------------ 2 files changed, 210 deletions(-) delete mode 100644 test/type_formatting/init.lua 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/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 thenend -]] -{ - ch = '\n', - edits = { - { - start = 12, - finish = 12, - text = '\n\t', - }, - { - start = 12, - finish = 13, - text = '', - }, - { - start = 13, - finish = 13, - text = '\ne', - }, - } -} - -TEST [[ - if true thenend -]] -{ - 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 -} -- cgit v1.2.3 From d0a712ddab9e0ecb9569870d2a26a6ce95d3e305 Mon Sep 17 00:00:00 2001 From: Tyler Miller Date: Sun, 28 Jul 2024 17:49:10 -0700 Subject: fix: incorrect `CompletionItemKind` for postfix snippets --- changelog.md | 1 + script/core/completion/postfix.lua | 2 +- test/completion/common.lua | 26 +++++++++++++------------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/changelog.md b/changelog.md index fadf1296..98d4e662 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ * `FIX` Inconsistent type narrow behavior of function call args [#2758](https://github.com/LuaLS/lua-language-server/issues/2758) * `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) ## 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/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, -- cgit v1.2.3 From d87be6dff95dfe00244e109c69aadb8a3c102928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 1 Aug 2024 17:52:53 +0800 Subject: fix wrong indent --- changelog.md | 6 ++- script/core/fix-indent.lua | 123 +++++++++++++++++++++++++++++++++++++++++---- script/parser/guide.lua | 2 + 3 files changed, 121 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index fadf1296..0bf05c01 100644 --- a/changelog.md +++ b/changelog.md @@ -14,7 +14,11 @@ * `CHG` Change spacing of parameter inlay hints to match other LSPs, like `rust-analyzer` * `FIX` Inconsistent type narrow behavior of function call args [#2758](https://github.com/LuaLS/lua-language-server/issues/2758) * `FIX` Typos in annotation descriptions -* `NEW` You can now click on "References" in CodeLen to display the reference list +* `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/fix-indent.lua b/script/core/fix-indent.lua index 2d1dc318..f9564dd8 100644 --- a/script/core/fix-indent.lua +++ b/script/core/fix-indent.lua @@ -1,19 +1,20 @@ 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 ---@param change table ----@param edits table[] -local function removeSpacesAfterEnter(state, change, edits) - if not change.text:match '^\r?\n[\t ]+\r?\n' then - return +local function removeSpacesAfterEnter(state, change) + if not change.text:match '^\r?\n[\t ]+\r?\n$' then + return false end local lines = state.originLines or state.lines 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) @@ -25,6 +26,7 @@ local function removeSpacesAfterEnter(state, change, edits) break end end + if leftOffset and leftOffset < startOffset then edits[#edits+1] = { start = leftOffset, @@ -43,6 +45,108 @@ local function removeSpacesAfterEnter(state, change, edits) text = '', } end + + if #edits == 0 then + return nil + end + + 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 + 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 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 + 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 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 = endOffset - #myIndent + #lastIndent, + finish = endOffset, + text = '', + } + + return edits end ---@param state parser.state @@ -90,11 +194,12 @@ return function (uri, changes) return end - local edits = {} local firstChange = changes[1] if firstChange.range then - removeSpacesAfterEnter(state, firstChange, edits) + 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/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, -- cgit v1.2.3