summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
Diffstat (limited to 'script')
-rw-r--r--script/core/code-action.lua18
-rw-r--r--script/core/command/removeSpace.lua2
-rw-r--r--script/core/command/solve.lua6
-rw-r--r--script/files.lua112
-rw-r--r--script/proto/define.lua97
-rw-r--r--script/provider/diagnostic.lua9
-rw-r--r--script/provider/provider.lua110
7 files changed, 162 insertions, 192 deletions
diff --git a/script/core/code-action.lua b/script/core/code-action.lua
index 2a0d9907..dfd935c5 100644
--- a/script/core/code-action.lua
+++ b/script/core/code-action.lua
@@ -65,9 +65,7 @@ end
local function solveUndefinedGlobal(uri, diag, results)
local ast = files.getAst(uri)
- local text = files.getText(uri)
- local lines = files.getLines(uri)
- local offset = define.offsetOfWord(lines, text, diag.range.start)
+ local offset = files.offsetOfWord(uri, diag.range.start)
guide.eachSourceContain(ast.ast, offset, function (source)
if source.type ~= 'getglobal' then
return
@@ -86,9 +84,7 @@ end
local function solveLowercaseGlobal(uri, diag, results)
local ast = files.getAst(uri)
- local text = files.getText(uri)
- local lines = files.getLines(uri)
- local offset = define.offsetOfWord(lines, text, diag.range.start)
+ local offset = files.offsetOfWord(uri, diag.range.start)
guide.eachSourceContain(ast.ast, offset, function (source)
if source.type ~= 'setglobal' then
return
@@ -100,12 +96,10 @@ local function solveLowercaseGlobal(uri, diag, results)
end
local function findSyntax(uri, diag)
- local ast = files.getAst(uri)
- local text = files.getText(uri)
- local lines = files.getLines(uri)
+ local ast = files.getAst(uri)
for _, err in ipairs(ast.errs) do
if err.type:lower():gsub('_', '-') == diag.code then
- local range = define.range(lines, text, err.start, err.finish)
+ local range = files.range(uri, err.start, err.finish)
if util.equal(range, diag.range) then
return err
end
@@ -205,9 +199,7 @@ local function solveSyntax(uri, diag, results)
end
local function solveNewlineCall(uri, diag, results)
- local text = files.getText(uri)
- local lines = files.getLines(uri)
- local start = define.unrange(lines, text, diag.range)
+ local start = files.unrange(uri, diag.range)
results[#results+1] = {
title = lang.script.ACTION_ADD_SEMICOLON,
kind = 'quickfix',
diff --git a/script/core/command/removeSpace.lua b/script/core/command/removeSpace.lua
index e8b09932..29513951 100644
--- a/script/core/command/removeSpace.lua
+++ b/script/core/command/removeSpace.lua
@@ -32,7 +32,7 @@ return function (data)
goto NEXT_LINE
end
textEdit[#textEdit+1] = {
- range = define.range(lines, text, start, finish),
+ range = files.range(uri, start, finish),
newText = '',
}
goto NEXT_LINE
diff --git a/script/core/command/solve.lua b/script/core/command/solve.lua
index d3b8f94e..ff14bf40 100644
--- a/script/core/command/solve.lua
+++ b/script/core/command/solve.lua
@@ -35,8 +35,8 @@ return function (data)
return
end
- local start = define.offsetOfWord(lines, text, data.range.start)
- local finish = define.offsetOfWord(lines, text, data.range['end'])
+ local start = files.offsetOfWord(uri, data.range.start)
+ local finish = files.offsetOfWord(uri, data.range['end'])
local result = guide.eachSourceContain(ast.ast, start, function (source)
if source.start ~= start
@@ -86,7 +86,7 @@ return function (data)
changes = {
[uri] = {
{
- range = define.range(lines, text, result.start, result.finish),
+ range = files.range(uri, result.start, result.finish),
newText = ('(%s)'):format(text:sub(result.start, result.finish)),
}
},
diff --git a/script/files.lua b/script/files.lua
index 48a5b58b..d5ff5981 100644
--- a/script/files.lua
+++ b/script/files.lua
@@ -9,6 +9,7 @@ local await = require 'await'
local timer = require 'timer'
local plugin = require 'plugin'
local util = require 'utility'
+local guide = require 'parser.guide'
local m = {}
@@ -364,6 +365,117 @@ function m.getUri(uri)
return uri
end
+---@alias position table
+
+--- 获取 position 对应的光标位置
+---@param uri uri
+---@param position position
+---@return integer
+function m.offset(uri, position)
+ local lines = m.getLines(uri)
+ local text = m.getText(uri)
+ if not lines then
+ return 0
+ end
+ local row = position.line + 1
+ local start = guide.lineRange(lines, row)
+ if start <= 0 or start > #text then
+ return #text + 1
+ end
+ local offset = utf8.offset(text, position.character + 1, start) or (#text + 1)
+ return offset - 1
+end
+
+--- 获取 position 对应的光标位置(根据附近的单词)
+---@param uri uri
+---@param position position
+---@return integer
+function m.offsetOfWord(uri, position)
+ local lines = m.getLines(uri)
+ local text = m.getText(uri)
+ if not lines then
+ return 0
+ end
+ local row = position.line + 1
+ local start = guide.lineRange(lines, row)
+ if start <= 0 or start > #text then
+ return #text + 1
+ end
+ local offset = utf8.offset(text, position.character + 1, start) or (#text + 1)
+ if offset > #text
+ or text:sub(offset-1, offset):match '[%w_][^%w_]' then
+ offset = offset - 1
+ end
+ return offset
+end
+
+--- 将光标位置转化为 position
+---@param uri uri
+---@param offset integer
+---@return position
+function m.position(uri, offset)
+ local lines = m.getLines(uri)
+ local text = m.getText(uri)
+ if not lines then
+ return {
+ line = 0,
+ character = 0,
+ }
+ end
+ local row, col = guide.positionOf(lines, offset)
+ local start, finish = guide.lineRange(lines, row, true)
+ if start < 1 then
+ start = 1
+ end
+ if col <= finish - start + 1 then
+ local ucol = util.utf8Len(text, start, start + col - 1)
+ if row < 1 then
+ row = 1
+ end
+ return {
+ line = row - 1,
+ character = ucol,
+ }
+ elseif col == 1 then
+ return {
+ line = row - 1,
+ character = 0,
+ }
+ else
+ return {
+ line = row,
+ character = 0,
+ }
+ end
+end
+
+--- 将起点与终点位置转化为 range
+---@alias range table
+---@param uri uri
+---@param offset1 integer
+---@param offset2 integer
+function m.range(uri, offset1, offset2)
+ local range = {
+ start = m.position(uri, offset1),
+ ['end'] = m.position(uri, offset2),
+ }
+ if range.start.character > 0 then
+ range.start.character = range.start.character - 1
+ end
+ return range
+end
+
+--- convert `range` to `offsetStart` and `offsetFinish`
+---@param uri table
+---@param range table
+---@return integer start
+---@return integer finish
+function m.unrange(uri, range)
+ local start = m.offset(uri, range.start)
+ local finish = m.offset(uri, range['end'])
+ return start, finish
+end
+
--- 获取文件的自定义缓存信息(在文件内容更新后自动失效)
function m.getCache(uri)
uri = getUriKey(uri)
diff --git a/script/proto/define.lua b/script/proto/define.lua
index 920571af..c4cffe14 100644
--- a/script/proto/define.lua
+++ b/script/proto/define.lua
@@ -3,103 +3,6 @@ local util = require 'utility'
local m = {}
---- 获取 position 对应的光标位置
----@param lines table
----@param text string
----@param position position
----@return integer
-function m.offset(lines, text, position)
- local row = position.line + 1
- local start = guide.lineRange(lines, row)
- if start <= 0 or start > #text then
- return #text + 1
- end
- local offset = utf8.offset(text, position.character + 1, start) or (#text + 1)
- return offset - 1
-end
-
---- 获取 position 对应的光标位置(根据附近的单词)
----@param lines table
----@param text string
----@param position position
----@return integer
-function m.offsetOfWord(lines, text, position)
- local row = position.line + 1
- local start = guide.lineRange(lines, row)
- if start <= 0 or start > #text then
- return #text + 1
- end
- local offset = utf8.offset(text, position.character + 1, start) or (#text + 1)
- if offset > #text
- or text:sub(offset-1, offset):match '[%w_][^%w_]' then
- offset = offset - 1
- end
- return offset
-end
-
---- 将光标位置转化为 position
----@alias position table
----@param lines table
----@param text string
----@param offset integer
----@return position
-function m.position(lines, text, offset)
- local row, col = guide.positionOf(lines, offset)
- local start, finish = guide.lineRange(lines, row, true)
- if start < 1 then
- start = 1
- end
- if col <= finish - start + 1 then
- local ucol = util.utf8Len(text, start, start + col - 1)
- if row < 1 then
- row = 1
- end
- return {
- line = row - 1,
- character = ucol,
- }
- elseif col == 1 then
- return {
- line = row - 1,
- character = 0,
- }
- else
- return {
- line = row,
- character = 0,
- }
- end
-end
-
---- 将起点与终点位置转化为 range
----@alias range table
----@param lines table
----@param text string
----@param offset1 integer
----@param offset2 integer
-function m.range(lines, text, offset1, offset2)
- local range = {
- start = m.position(lines, text, offset1),
- ['end'] = m.position(lines, text, offset2),
- }
- if range.start.character > 0 then
- range.start.character = range.start.character - 1
- end
- return range
-end
-
---- convert `range` to `offsetStart` and `offsetFinish`
----@param lines table
----@param text string
----@param range table
----@return integer start
----@return integer finish
-function m.unrange(lines, text, range)
- local start = m.offset(lines, text, range.start)
- local finish = m.offset(lines, text, range['end'])
- return start, finish
-end
-
---@alias location table
---@param uri string
---@param range range
diff --git a/script/provider/diagnostic.lua b/script/provider/diagnostic.lua
index acea679a..9be9f87a 100644
--- a/script/provider/diagnostic.lua
+++ b/script/provider/diagnostic.lua
@@ -46,14 +46,14 @@ local function buildSyntaxError(uri, err)
end
relatedInformation[#relatedInformation+1] = {
message = rmessage,
- location = define.location(uri, define.range(lines, text, rel.start, rel.finish)),
+ location = define.location(uri, files.range(uri, rel.start, rel.finish)),
}
end
end
return {
code = err.type:lower():gsub('_', '-'),
- range = define.range(lines, text, err.start, err.finish),
+ range = files.range(uri, err.start, err.finish),
severity = define.DiagnosticSeverity.Error,
source = lang.script.DIAG_SYNTAX_CHECK,
message = message,
@@ -73,16 +73,15 @@ local function buildDiagnostic(uri, diag)
relatedInformation = {}
for _, rel in ipairs(diag.related) do
local rtext = files.getText(rel.uri)
- local rlines = files.getLines(rel.uri)
relatedInformation[#relatedInformation+1] = {
message = rel.message or rtext:sub(rel.start, rel.finish),
- location = define.location(rel.uri, define.range(rlines, rtext, rel.start, rel.finish))
+ location = define.location(rel.uri, files.range(rel.uri, rel.start, rel.finish))
}
end
end
return {
- range = define.range(lines, text, diag.start, diag.finish),
+ range = files.range(uri, diag.start, diag.finish),
source = lang.script.DIAG_DIAGNOSTICS,
severity = diag.level,
message = diag.message,
diff --git a/script/provider/provider.lua b/script/provider/provider.lua
index bc6694f4..ef300e02 100644
--- a/script/provider/provider.lua
+++ b/script/provider/provider.lua
@@ -191,8 +191,7 @@ proto.on('textDocument/didChange', function (params)
local text = files.getOriginText(uri) or ''
for _, change in ipairs(changes) do
if change.range then
- local lines = files.getLines(uri)
- local start, finish = define.unrange(lines, text, change.range)
+ local start, finish = files.unrange(uri, change.range)
text = text:sub(1, start) .. change.text .. text:sub(finish + 1)
else
text = change.text
@@ -210,9 +209,7 @@ proto.on('textDocument/hover', function (params)
if not files.exists(uri) then
return nil
end
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- local offset = define.offsetOfWord(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local hover = core.byUri(uri, offset)
if not hover then
return nil
@@ -229,7 +226,7 @@ proto.on('textDocument/hover', function (params)
value = md:string(),
kind = 'markdown',
},
- range = define.range(lines, text, hover.source.start, hover.source.finish),
+ range = files.range(uri, hover.source.start, hover.source.finish),
}
end)
@@ -241,7 +238,7 @@ proto.on('textDocument/definition', function (params)
end
local lines = files.getLines(uri)
local text = files.getText(uri)
- local offset = define.offsetOfWord(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local result = core(uri, offset)
if not result then
return nil
@@ -251,12 +248,11 @@ proto.on('textDocument/definition', function (params)
local targetUri = info.uri
if targetUri then
local targetLines = files.getLines(targetUri)
- local targetText = files.getText(targetUri)
if targetLines then
response[i] = define.locationLink(targetUri
- , define.range(targetLines, targetText, info.target.start, info.target.finish)
- , define.range(targetLines, targetText, info.target.start, info.target.finish)
- , define.range(lines, text, info.source.start, info.source.finish)
+ , files.range(targetUri, info.target.start, info.target.finish)
+ , files.range(targetUri, info.target.start, info.target.finish)
+ , files.range(uri, info.source.start, info.source.finish)
)
end
end
@@ -272,7 +268,7 @@ proto.on('textDocument/references', function (params)
end
local lines = files.getLines(uri)
local text = files.getText(uri)
- local offset = define.offsetOfWord(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local result = core(uri, offset)
if not result then
return nil
@@ -280,10 +276,8 @@ proto.on('textDocument/references', function (params)
local response = {}
for i, info in ipairs(result) do
local targetUri = info.uri
- local targetLines = files.getLines(targetUri)
- local targetText = files.getText(targetUri)
response[i] = define.location(targetUri
- , define.range(targetLines, targetText, info.target.start, info.target.finish)
+ , files.range(targetUri, info.target.start, info.target.finish)
)
end
return response
@@ -295,9 +289,7 @@ proto.on('textDocument/documentHighlight', function (params)
if not files.exists(uri) then
return nil
end
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- local offset = define.offsetOfWord(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local result = core(uri, offset)
if not result then
return nil
@@ -305,7 +297,7 @@ proto.on('textDocument/documentHighlight', function (params)
local response = {}
for _, info in ipairs(result) do
response[#response+1] = {
- range = define.range(lines, text, info.start, info.finish),
+ range = files.range(uri, info.start, info.finish),
kind = info.kind,
}
end
@@ -318,9 +310,7 @@ proto.on('textDocument/rename', function (params)
if not files.exists(uri) then
return nil
end
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- local offset = define.offsetOfWord(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local result = core.rename(uri, offset, params.newName)
if not result then
return nil
@@ -330,12 +320,10 @@ proto.on('textDocument/rename', function (params)
}
for _, info in ipairs(result) do
local ruri = info.uri
- local rlines = files.getLines(ruri)
- local rtext = files.getText(ruri)
if not workspaceEdit.changes[ruri] then
workspaceEdit.changes[ruri] = {}
end
- local textEdit = define.textEdit(define.range(rlines, rtext, info.start, info.finish), info.text)
+ local textEdit = define.textEdit(files.range(ruri, info.start, info.finish), info.text)
workspaceEdit.changes[ruri][#workspaceEdit.changes[ruri]+1] = textEdit
end
return workspaceEdit
@@ -347,15 +335,13 @@ proto.on('textDocument/prepareRename', function (params)
if not files.exists(uri) then
return nil
end
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- local offset = define.offsetOfWord(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local result = core.prepareRename(uri, offset)
if not result then
return nil
end
return {
- range = define.range(lines, text, result.start, result.finish),
+ range = files.range(uri, result.start, result.finish),
placeholder = result.text,
}
end)
@@ -371,9 +357,7 @@ proto.on('textDocument/completion', function (params)
end
await.setPriority(1000)
local clock = os.clock()
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- local offset = define.offset(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local result = core.completion(uri, offset)
local passed = os.clock() - clock
if passed > 0.1 then
@@ -396,9 +380,8 @@ proto.on('textDocument/completion', function (params)
commitCharacters = res.commitCharacters,
command = res.command,
textEdit = res.textEdit and {
- range = define.range(
- lines,
- text,
+ range = files.range(
+ uri,
res.textEdit.start,
res.textEdit.finish
),
@@ -408,9 +391,8 @@ proto.on('textDocument/completion', function (params)
local t = {}
for j, edit in ipairs(res.additionalTextEdits) do
t[j] = {
- range = define.range(
- lines,
- text,
+ range = files.range(
+ uri,
edit.start,
edit.finish
),
@@ -467,8 +449,6 @@ proto.on('completionItem/resolve', function (item)
if not resolved then
return nil
end
- local lines = files.getLines(uri)
- local text = files.getText(uri)
item.detail = resolved.detail
item.documentation = resolved.description and {
value = resolved.description,
@@ -478,9 +458,8 @@ proto.on('completionItem/resolve', function (item)
local t = {}
for j, edit in ipairs(resolved.additionalTextEdits) do
t[j] = {
- range = define.range(
- lines,
- text,
+ range = files.range(
+ uri,
edit.start,
edit.finish
),
@@ -502,9 +481,7 @@ proto.on('textDocument/signatureHelp', function (params)
end
await.close('signatureHelp')
await.setID('signatureHelp')
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- local offset = define.offset(lines, text, params.position)
+ local offset = files.offsetOfWord(uri, params.position)
local core = require 'core.signature'
local results = core(uri, offset)
if not results then
@@ -539,12 +516,8 @@ end)
proto.on('textDocument/documentSymbol', function (params)
local core = require 'core.document-symbol'
local uri = params.textDocument.uri
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- while not lines or not text do
+ while not files.getLines(uri) do
await.sleep(0.1)
- lines = files.getLines(uri)
- text = files.getText(uri)
end
local symbols = core(uri)
@@ -554,15 +527,13 @@ proto.on('textDocument/documentSymbol', function (params)
local function convert(symbol)
await.delay()
- symbol.range = define.range(
- lines,
- text,
+ symbol.range = files.range(
+ uri,
symbol.range[1],
symbol.range[2]
)
- symbol.selectionRange = define.range(
- lines,
- text,
+ symbol.selectionRange = files.range(
+ uri,
symbol.selectionRange[1],
symbol.selectionRange[2]
)
@@ -595,7 +566,7 @@ proto.on('textDocument/codeAction', function (params)
return nil
end
- local start, finish = define.unrange(lines, text, range)
+ local start, finish = files.unrange(uri, range)
local results = core(uri, start, finish, diagnostics)
if not results or #results == 0 then
@@ -605,10 +576,8 @@ proto.on('textDocument/codeAction', function (params)
for _, res in ipairs(results) do
if res.edit then
for turi, changes in pairs(res.edit.changes) do
- local ttext = files.getText(turi)
- local tlines = files.getLines(turi)
for _, change in ipairs(changes) do
- change.range = define.range(tlines, ttext, change.start, change.finish)
+ change.range = files.range(turi, change.start, change.finish)
change.start = nil
change.finish = nil
end
@@ -644,9 +613,8 @@ proto.on('workspace/symbol', function (params)
local function convert(symbol)
symbol.location = define.location(
symbol.uri,
- define.range(
- files.getLines(symbol.uri),
- files.getText(symbol.uri),
+ files.range(
+ symbol.uri,
symbol.range[1],
symbol.range[2]
)
@@ -681,15 +649,11 @@ proto.on('textDocument/semanticTokens/range', function (params)
local core = require 'core.semantic-tokens'
local uri = params.textDocument.uri
log.debug('semanticTokens/range', uri)
- local lines = files.getLines(uri)
- local text = files.getText(uri)
- while not lines or not text do
+ while not files.getLines(uri) do
await.sleep(0.1)
- lines = files.getLines(uri)
- text = files.getText(uri)
end
- local start = define.offset(lines, text, params.range.start)
- local finish = define.offset(lines, text, params.range['end'])
+ local start = files.offsetOfWord(uri, params.range.start)
+ local finish = files.offsetOfWord(uri, params.range['end'])
local results = core(uri, start, finish)
return {
data = results
@@ -711,8 +675,8 @@ proto.on('textDocument/foldingRange', function (params)
local results = {}
for _, region in ipairs(regions) do
- local startLine = define.position(lines, text, region.start).line
- local endLine = define.position(lines, text, region.finish).line
+ local startLine = files.position(uri, region.start).line
+ local endLine = files.position(uri, region.finish).line
if not region.hideLastLine then
endLine = endLine - 1
end