summaryrefslogtreecommitdiff
path: root/script/core/command/solve.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2020-11-20 21:57:09 +0800
committer最萌小汐 <sumneko@hotmail.com>2020-11-20 21:57:09 +0800
commit4ca61ec457822dd14966afa0752340ae8ce180a1 (patch)
treeae8adb1ad82c717868e551e699fd3cf3bb290089 /script/core/command/solve.lua
parentc63b2e404d8d2bb984afe3678a5ba2b2836380cc (diff)
downloadlua-language-server-4ca61ec457822dd14966afa0752340ae8ce180a1.zip
no longer beta
Diffstat (limited to 'script/core/command/solve.lua')
-rw-r--r--script/core/command/solve.lua96
1 files changed, 96 insertions, 0 deletions
diff --git a/script/core/command/solve.lua b/script/core/command/solve.lua
new file mode 100644
index 00000000..d3b8f94e
--- /dev/null
+++ b/script/core/command/solve.lua
@@ -0,0 +1,96 @@
+local files = require 'files'
+local define = require 'proto.define'
+local guide = require 'parser.guide'
+local proto = require 'proto'
+local lang = require 'language'
+
+local opMap = {
+ ['+'] = true,
+ ['-'] = true,
+ ['*'] = true,
+ ['/'] = true,
+ ['//'] = true,
+ ['^'] = true,
+ ['<<'] = true,
+ ['>>'] = true,
+ ['&'] = true,
+ ['|'] = true,
+ ['~'] = true,
+ ['..'] = true,
+}
+
+local literalMap = {
+ ['number'] = true,
+ ['boolean'] = true,
+ ['string'] = true,
+ ['table'] = true,
+}
+
+return function (data)
+ local uri = data.uri
+ local lines = files.getLines(uri)
+ local text = files.getText(uri)
+ local ast = files.getAst(uri)
+ if not ast then
+ return
+ end
+
+ local start = define.offsetOfWord(lines, text, data.range.start)
+ local finish = define.offsetOfWord(lines, text, data.range['end'])
+
+ local result = guide.eachSourceContain(ast.ast, start, function (source)
+ if source.start ~= start
+ or source.finish ~= finish then
+ return
+ end
+ if not source.op or source.op.type ~= 'or' then
+ return
+ end
+ local first = source[1]
+ local second = source[2]
+ -- a + b or 0 --> a + (b or 0)
+ do
+ if first.op
+ and opMap[first.op.type]
+ and first.type ~= 'unary'
+ and not second.op
+ and literalMap[second.type] then
+ return {
+ start = source[1][2].start,
+ finish = source[2].finish,
+ }
+ end
+ end
+ -- a or b + c --> (a or b) + c
+ do
+ if second.op
+ and opMap[second.op.type]
+ and second.type ~= 'unary'
+ and not first.op
+ and literalMap[second[1].type] then
+ return {
+ start = source[1].start,
+ finish = source[2][1].finish,
+ }
+ end
+ end
+ end)
+
+ if not result then
+ return
+ end
+
+ proto.awaitRequest('workspace/applyEdit', {
+ label = lang.script.COMMAND_REMOVE_SPACE,
+ edit = {
+ changes = {
+ [uri] = {
+ {
+ range = define.range(lines, text, result.start, result.finish),
+ newText = ('(%s)'):format(text:sub(result.start, result.finish)),
+ }
+ },
+ }
+ },
+ })
+end