summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2024-08-01 17:52:53 +0800
committer最萌小汐 <sumneko@hotmail.com>2024-08-01 17:52:53 +0800
commitd87be6dff95dfe00244e109c69aadb8a3c102928 (patch)
treef0bdd455f5adc5c6822369fa682a9facad580bc2
parent1c7755b317d1e811a3f71f3ec745800555575fd0 (diff)
downloadlua-language-server-d87be6dff95dfe00244e109c69aadb8a3c102928.zip
fix wrong indent
-rw-r--r--changelog.md6
-rw-r--r--script/core/fix-indent.lua123
-rw-r--r--script/parser/guide.lua2
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,