summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-03-12 17:03:03 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-03-12 17:03:03 +0800
commit3517513487ab039bf704938d03897686c3f6d6ad (patch)
treeea5a09e2137447a1a132ebb3524d02ca2fad83a4
parent6b7a952d6537f389a85df7928ded74ca9c81eee0 (diff)
parent062bb1ce750a4a7a37b38452b9cf196c491cc6e5 (diff)
downloadlua-language-server-3517513487ab039bf704938d03897686c3f6d6ad.zip
Merge branch 'text-merger'
-rw-r--r--changelog.md1
-rw-r--r--script/files.lua30
-rw-r--r--script/parser/guide.lua5
-rw-r--r--script/provider/provider.lua15
-rw-r--r--script/service/service.lua22
-rw-r--r--script/text-merger.lua99
-rw-r--r--script/utility.lua25
-rw-r--r--test/basic/init.lua132
-rw-r--r--test/crossfile/definition.lua4
9 files changed, 279 insertions, 54 deletions
diff --git a/changelog.md b/changelog.md
index c2749cd0..ee1e265e 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,7 @@
# changelog
## 1.19.0
+* `CHG` text-document-synchronization: refactored
* `FIX` missed syntax error `function m['x']() end`
## 1.18.1
diff --git a/script/files.lua b/script/files.lua
index b085e7fd..3f3d633e 100644
--- a/script/files.lua
+++ b/script/files.lua
@@ -19,6 +19,7 @@ if platform.OS == 'Windows' then
unicode = require 'bee.unicode'
end
+---@class files
local m = {}
m.openMap = {}
@@ -206,6 +207,24 @@ function m.setRawText(uri, text)
m.astMap[uri] = nil
end
+function m.getCachedRows(uri)
+ uri = getUriKey(uri)
+ local file = m.fileMap[uri]
+ if not file then
+ return nil
+ end
+ return file.rows
+end
+
+function m.setCachedRows(uri, rows)
+ uri = getUriKey(uri)
+ local file = m.fileMap[uri]
+ if not file then
+ return
+ end
+ file.rows = rows
+end
+
--- 获取文件版本
function m.getVersion(uri)
uri = getUriKey(uri)
@@ -633,17 +652,6 @@ function m.diffedOffsetBack(uri, offset)
return smerger.getOffsetBack(file._diffInfo, offset)
end
-function m.clearDiff(uri)
- uri = m.getUri(uri)
- local file = m.fileMap[uri]
- if not file then
- return
- end
- file._diffInfo = nil
- file.text = file.originText
- m.linesMap[uri] = m.originLinesMap[uri]
-end
-
--- 将光标位置转化为 position
---@param uri uri
---@param offset integer
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index 81adf890..377b2823 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -2404,6 +2404,7 @@ function m.searchSameFieldsInValue(status, ref, start, pushQueue, mode)
if not m.checkValueMark(status, ref, value) then
--return
end
+ status.share.inSetValue = (status.share.inSetValue or 0) + 1
if not status.share.tempValueMark then
status.share.tempValueMark = {}
end
@@ -2417,6 +2418,7 @@ function m.searchSameFieldsInValue(status, ref, start, pushQueue, mode)
end
pushQueue(value, start, true)
end
+ status.share.inSetValue = (status.share.inSetValue or 0) - 1
-- 检查形如 a = f() 的分支情况
m.checkSameSimpleInCall(status, value, start, pushQueue, mode)
end
@@ -2475,6 +2477,9 @@ function m.checkSameSimpleAsSetValue(status, ref, start, pushQueue)
if not status.deep then
--return
end
+ if status.share.inSetValue and status.share.inSetValue > 0 then
+ return
+ end
if ref.type == 'select' then
return
end
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index 917f66cc..66031f15 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -17,6 +17,7 @@ local fs = require 'bee.filesystem'
local lang = require 'language'
local plugin = require 'plugin'
local progress = require 'progress'
+local tm = require 'text-merger'
local function updateConfig()
local diagnostics = require 'provider.diagnostic'
@@ -270,18 +271,8 @@ proto.on('textDocument/didChange', function (params)
if not files.isLua(uri) and not files.isOpen(uri) then
return
end
- files.clearDiff(uri)
- local text = files.getText(uri) or ''
- for _, change in ipairs(changes) do
- if change.range then
- local start, finish = files.unrange(uri, change.range)
- text = text:sub(1, start - 1) .. change.text .. text:sub(finish)
- else
- text = change.text
- end
- files.setRawText(uri, text)
- end
- files.setRawText(uri, '')
+ --log.debug('changes', util.dump(changes))
+ local text = tm(uri, changes)
files.setText(uri, text, true)
end)
diff --git a/script/service/service.lua b/script/service/service.lua
index 14f05ada..44fd9aa4 100644
--- a/script/service/service.lua
+++ b/script/service/service.lua
@@ -141,16 +141,15 @@ end
function m.startTimer()
pub.task('timer', 1)
while true do
- pub.step(not m.working)
+ pub.step(not m.workingClock)
if await.step() then
m.sleeping = false
- if not m.working then
- m.working = true
- m.reportStatus()
+ if not m.workingClock then
+ m.workingClock = time.monotonic()
end
else
- if m.working then
- m.working = false
+ if m.workingClock then
+ m.workingClock = nil
m.idleClock = time.monotonic()
m.reportStatus()
end
@@ -159,9 +158,9 @@ function m.startTimer()
end
end
-function m.checkSleep()
+function m.pulse()
timer.loop(10, function ()
- if not m.working and not m.sleeping and time.monotonic() - m.idleClock >= 300000 then
+ if not m.workingClock and not m.sleeping and time.monotonic() - m.idleClock >= 300000 then
m.sleeping = true
files.flushCache()
vm.flushCache()
@@ -171,11 +170,14 @@ function m.checkSleep()
end
m.reportStatus()
end)
+ timer.loop(0.1, function ()
+ m.reportStatus()
+ end)
end
function m.reportStatus()
local info = {}
- if m.working then
+ if m.workingClock and time.monotonic() - m.workingClock > 100 then
info.text = '$(loading~spin)Lua'
elseif m.sleeping then
info.text = "💤Lua"
@@ -212,7 +214,7 @@ function m.start()
pub.recruitBraves(4)
proto.listen()
m.report()
- m.checkSleep()
+ m.pulse()
m.reportStatus()
m.testVersion()
diff --git a/script/text-merger.lua b/script/text-merger.lua
new file mode 100644
index 00000000..aa124fdd
--- /dev/null
+++ b/script/text-merger.lua
@@ -0,0 +1,99 @@
+local files = require 'files'
+local util = require 'utility'
+
+local function splitRows(text)
+ local rows = {}
+ for line in util.eachLine(text, true) do
+ rows[#rows+1] = line
+ end
+ return rows
+end
+
+local function getLeft(text, char)
+ local left
+ local length = util.utf8Len(text)
+
+ if char == 0 then
+ left = ''
+ elseif char >= length then
+ left = text
+ else
+ left = text:sub(1, utf8.offset(text, char + 1) - 1)
+ end
+
+ return left
+end
+
+local function getRight(text, char)
+ local right
+ local length = util.utf8Len(text)
+
+ if char == 0 then
+ right = text
+ elseif char >= length then
+ right = ''
+ else
+ right = text:sub(utf8.offset(text, char + 1))
+ end
+
+ return right
+end
+
+local function mergeRows(rows, change)
+ local startLine = change.range['start'].line + 1
+ local startChar = change.range['start'].character
+ local endLine = change.range['end'].line + 1
+ local endChar = change.range['end'].character
+
+ local insertRows = splitRows(change.text)
+ local newEndLine = startLine + #insertRows - 1
+ local left = getLeft(rows[startLine], startChar)
+ local right = getRight(rows[endLine], endChar)
+ -- 先把双方的行数调整成一致
+ local delta = #insertRows - (endLine - startLine + 1)
+ if delta ~= 0 then
+ table.move(rows, endLine, #rows, endLine + delta)
+ -- 如果行数变少了,要清除多余的行
+ if delta < 0 then
+ for i = #rows, #rows + delta + 1, -1 do
+ rows[i] = nil
+ end
+ end
+ end
+ -- 先处理第一行和最后一行
+ if startLine == newEndLine then
+ rows[startLine] = left .. insertRows[1] .. right
+ else
+ rows[startLine] = left .. insertRows[1]
+ rows[newEndLine] = insertRows[#insertRows] .. right
+ end
+ -- 修改中间的每一行
+ for i = 2, #insertRows - 1 do
+ local currentLine = startLine + i - 1
+ local insertText = insertRows[i]
+ rows[currentLine] = insertText
+ end
+end
+
+return function (uri, changes)
+ local text
+ for _, change in ipairs(changes) do
+ if change.range then
+ local rows = files.getCachedRows(uri)
+ if not rows then
+ text = text or files.getOriginText(uri)
+ rows = splitRows(text)
+ end
+ mergeRows(rows, change)
+ files.setCachedRows(uri, rows)
+ else
+ files.setCachedRows(uri, nil)
+ text = change.text
+ end
+ end
+ local rows = files.getCachedRows(uri)
+ if rows then
+ text = table.concat(rows)
+ end
+ return text
+end
diff --git a/script/utility.lua b/script/utility.lua
index a1eec7eb..a98bef92 100644
--- a/script/utility.lua
+++ b/script/utility.lua
@@ -547,24 +547,43 @@ function m.tableMultiRemove(t, index)
end
end
-function m.eachLine(text)
+---遍历文本的每一行
+---@param text string
+---@param keepNL boolean # 保留换行符
+---@return fun(text:string):string
+function m.eachLine(text, keepNL)
local offset = 1
local lineCount = 0
+ local lastLine
return function ()
if offset > #text then
+ if not lastLine then
+ lastLine = ''
+ return ''
+ end
return nil
end
lineCount = lineCount + 1
local nl = text:find('[\r\n]', offset)
if not nl then
- local lastLine = text:sub(offset)
+ lastLine = text:sub(offset)
offset = #text + 1
return lastLine
end
- local line = text:sub(offset, nl - 1)
+ local line
if text:sub(nl, nl + 1) == '\r\n' then
+ if keepNL then
+ line = text:sub(offset, nl + 1)
+ else
+ line = text:sub(offset, nl - 1)
+ end
offset = nl + 2
else
+ if keepNL then
+ line = text:sub(offset, nl)
+ else
+ line = text:sub(offset, nl - 1)
+ end
offset = nl + 1
end
return line
diff --git a/test/basic/init.lua b/test/basic/init.lua
index f809a2f3..a3a11f62 100644
--- a/test/basic/init.lua
+++ b/test/basic/init.lua
@@ -1,15 +1,31 @@
local files = require 'files'
+local tm = require 'text-merger'
-local text = [[
+local function TEST(source)
+ return function (expect)
+ return function (changes)
+ files.removeAll()
+ files.setText('', source)
+ local text = tm('', changes)
+ assert(text == expect)
+ end
+ end
+end
+
+TEST [[
+
+
+function Test(self)
+
+end
+]][[
function Test(self)
end
-]]
-files.setText('', text)
-local changes = {
+asser]]{
[1] = {
range = {
["end"] = {
@@ -97,21 +113,107 @@ local changes = {
},
}
-for _, change in ipairs(changes) do
- if change.range then
- local start, finish = files.unrange('', change.range)
- text = text:sub(1, start - 1) .. change.text .. text:sub(finish)
- else
- text = change.text
- end
- files.setRawText('', text)
+TEST [[
+local mt = {}
+
+function mt['xxx']()
+
+
+
end
+]] [[
+local mt = {}
-assert(text == [[
+function mt['xxx']()
+
+end
+]] {
+ [1] = {
+ range = {
+ ["end"] = {
+ character = 4,
+ line = 5,
+ },
+ start = {
+ character = 4,
+ line = 3,
+ },
+ },
+ rangeLength = 8,
+ text = "",
+ },
+}
+TEST [[
+local mt = {}
-function Test(self)
+function mt['xxx']()
+
+end
+]] [[
+local mt = {}
+function mt['xxx']()
+ p
end
+]] {
+ [1] = {
+ range = {
+ ["end"] = {
+ character = 4,
+ line = 3,
+ },
+ start = {
+ character = 4,
+ line = 3,
+ },
+ },
+ rangeLength = 0,
+ text = "p",
+ },
+}
+
+TEST [[
+print(12345)
+]] [[
+print(123
+45)
+]] {
+ [1] = {
+ range = {
+ ["end"] = {
+ character = 9,
+ line = 0,
+ },
+ start = {
+ character = 9,
+ line = 0,
+ },
+ },
+ rangeLength = 0,
+ text = "\
+",
+ },
+}
-asser]])
+TEST [[
+print(123
+45)
+]] [[
+print(12345)
+]] {
+ [1] = {
+ range = {
+ ["end"] = {
+ character = 0,
+ line = 1,
+ },
+ start = {
+ character = 9,
+ line = 0,
+ },
+ },
+ rangeLength = 2,
+ text = "",
+ },
+}
diff --git a/test/crossfile/definition.lua b/test/crossfile/definition.lua
index 9ee90de2..24c97321 100644
--- a/test/crossfile/definition.lua
+++ b/test/crossfile/definition.lua
@@ -564,9 +564,7 @@ TEST {
{
path = 'a.lua',
content = [[
- local t = GlobalTable
-
- t.settings = {
+ GlobalTable.settings = {
<!test!> = 1
}
]],