summaryrefslogtreecommitdiff
path: root/server-beta/src/core
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-11-22 23:26:32 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-11-22 23:26:32 +0800
commitd0ff66c9abe9d6abbca12fd811e0c3cb69c1033a (patch)
treebb34518d70b85de7656dbdbe958dfa221a3ff3b3 /server-beta/src/core
parent0a2c2ad15e1ec359171fb0dd4c72e57c5b66e9ba (diff)
downloadlua-language-server-d0ff66c9abe9d6abbca12fd811e0c3cb69c1033a.zip
整理一下目录结构
Diffstat (limited to 'server-beta/src/core')
-rw-r--r--server-beta/src/core/definition.lua105
-rw-r--r--server-beta/src/core/diagnostics/ambiguity-1.lua69
-rw-r--r--server-beta/src/core/diagnostics/duplicate-index.lua62
-rw-r--r--server-beta/src/core/diagnostics/emmy-lua.lua3
-rw-r--r--server-beta/src/core/diagnostics/empty-block.lua49
-rw-r--r--server-beta/src/core/diagnostics/global-in-nil-env.lua66
-rw-r--r--server-beta/src/core/diagnostics/init.lua41
-rw-r--r--server-beta/src/core/diagnostics/lowercase-global.lua39
-rw-r--r--server-beta/src/core/diagnostics/newfield-call.lua37
-rw-r--r--server-beta/src/core/diagnostics/newline-call.lua38
-rw-r--r--server-beta/src/core/diagnostics/redefined-local.lua32
-rw-r--r--server-beta/src/core/diagnostics/redundant-parameter.lua102
-rw-r--r--server-beta/src/core/diagnostics/redundant-value.lua24
-rw-r--r--server-beta/src/core/diagnostics/trailing-space.lua55
-rw-r--r--server-beta/src/core/diagnostics/undefined-env-child.lua32
-rw-r--r--server-beta/src/core/diagnostics/undefined-global.lua63
-rw-r--r--server-beta/src/core/diagnostics/unused-function.lua45
-rw-r--r--server-beta/src/core/diagnostics/unused-label.lua22
-rw-r--r--server-beta/src/core/diagnostics/unused-local.lua46
-rw-r--r--server-beta/src/core/diagnostics/unused-vararg.lua31
-rw-r--r--server-beta/src/core/highlight.lua230
-rw-r--r--server-beta/src/core/hover/arg.lua20
-rw-r--r--server-beta/src/core/hover/init.lua56
-rw-r--r--server-beta/src/core/hover/label.lua103
-rw-r--r--server-beta/src/core/hover/name.lua64
-rw-r--r--server-beta/src/core/hover/return.lua34
-rw-r--r--server-beta/src/core/hover/table.lua35
-rw-r--r--server-beta/src/core/reference.lua84
-rw-r--r--server-beta/src/core/rename.lua374
29 files changed, 0 insertions, 1961 deletions
diff --git a/server-beta/src/core/definition.lua b/server-beta/src/core/definition.lua
deleted file mode 100644
index 865fc7cb..00000000
--- a/server-beta/src/core/definition.lua
+++ /dev/null
@@ -1,105 +0,0 @@
-local guide = require 'parser.guide'
-local workspace = require 'workspace'
-local files = require 'files'
-local vm = require 'vm'
-
-local function findDef(source, callback)
- if source.type ~= 'local'
- and source.type ~= 'getlocal'
- and source.type ~= 'setlocal'
- and source.type ~= 'setglobal'
- and source.type ~= 'getglobal'
- and source.type ~= 'field'
- and source.type ~= 'method'
- and source.type ~= 'string'
- and source.type ~= 'number'
- and source.type ~= 'boolean'
- and source.type ~= 'goto' then
- return
- end
- vm.eachDef(source, function (info)
- if info.mode == 'declare'
- or info.mode == 'set'
- or info.mode == 'return' then
- local src = info.source
- local root = guide.getRoot(src)
- local uri = root.uri
- if src.type == 'setfield'
- or src.type == 'getfield'
- or src.type == 'tablefield' then
- callback(src.field, uri)
- elseif src.type == 'setindex'
- or src.type == 'getindex'
- or src.type == 'tableindex' then
- callback(src.index, uri)
- elseif src.type == 'getmethod'
- or src.type == 'setmethod' then
- callback(src.method, uri)
- else
- callback(src, uri)
- end
- end
- end)
-end
-
-local function checkRequire(source, offset, callback)
- if source.type ~= 'call' then
- return
- end
- local func = source.node
- local pathSource = source.args and source.args[1]
- if not pathSource then
- return
- end
- if not guide.isContain(pathSource, offset) then
- return
- end
- local literal = guide.getLiteral(pathSource)
- if type(literal) ~= 'string' then
- return
- end
- local name = func.special
- if name == 'require' then
- local result = workspace.findUrisByRequirePath(literal, true)
- for _, uri in ipairs(result) do
- callback(uri)
- end
- elseif name == 'dofile'
- or name == 'loadfile' then
- local result = workspace.findUrisByFilePath(literal, true)
- for _, uri in ipairs(result) do
- callback(uri)
- end
- end
-end
-
-return function (uri, offset)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
- local results = {}
- guide.eachSourceContain(ast.ast, offset, function (source)
- checkRequire(source, offset, function (uri)
- results[#results+1] = {
- uri = files.getOriginUri(uri),
- source = source,
- target = {
- start = 0,
- finish = 0,
- }
- }
- end)
- findDef(source, function (target, uri)
- results[#results+1] = {
- target = target,
- uri = files.getOriginUri(uri),
- source = source,
- }
- end)
- end)
- if #results == 0 then
- return nil
- end
- return results
-end
diff --git a/server-beta/src/core/diagnostics/ambiguity-1.lua b/server-beta/src/core/diagnostics/ambiguity-1.lua
deleted file mode 100644
index 37815fb5..00000000
--- a/server-beta/src/core/diagnostics/ambiguity-1.lua
+++ /dev/null
@@ -1,69 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-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 (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- local text = files.getText(uri)
- guide.eachSourceType(ast.ast, 'binary', function (source)
- if 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 opMap[first.op and first.op.type]
- and first.type ~= 'unary'
- and not second.op
- and literalMap[second.type]
- and not literalMap[first[2].type]
- then
- callback {
- start = source.start,
- finish = source.finish,
- message = lang.script('DIAG_AMBIGUITY_1', text:sub(first.start, first.finish))
- }
- end
- end
- -- (a or 0) + c --> a or (0 + c)
- do
- if opMap[second.op and second.op.type]
- and second.type ~= 'unary'
- and not first.op
- and literalMap[second[1].type]
- then
- callback {
- start = source.start,
- finish = source.finish,
- message = lang.script('DIAG_AMBIGUITY_1', text:sub(second.start, second.finish))
- }
- end
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/duplicate-index.lua b/server-beta/src/core/diagnostics/duplicate-index.lua
deleted file mode 100644
index 76b1c958..00000000
--- a/server-beta/src/core/diagnostics/duplicate-index.lua
+++ /dev/null
@@ -1,62 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-local define = require 'proto.define'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- guide.eachSourceType(ast.ast, 'table', function (source)
- local mark = {}
- for _, obj in ipairs(source) do
- if obj.type == 'tablefield'
- or obj.type == 'tableindex' then
- local name = guide.getKeyName(obj)
- if name then
- if not mark[name] then
- mark[name] = {}
- end
- mark[name][#mark[name]+1] = obj.field or obj.index
- end
- end
- end
-
- for name, defs in pairs(mark) do
- local sname = name:match '^.|(.+)$'
- if #defs > 1 and sname then
- local related = {}
- for i = 1, #defs do
- local def = defs[i]
- related[i] = {
- start = def.start,
- finish = def.finish,
- uri = uri,
- }
- end
- for i = 1, #defs - 1 do
- local def = defs[i]
- callback {
- start = def.start,
- finish = def.finish,
- related = related,
- message = lang.script('DIAG_DUPLICATE_INDEX', sname),
- level = define.DiagnosticSeverity.Hint,
- tags = { define.DiagnosticTag.Unnecessary },
- }
- end
- for i = #defs, #defs do
- local def = defs[i]
- callback {
- start = def.start,
- finish = def.finish,
- related = related,
- message = lang.script('DIAG_DUPLICATE_INDEX', sname),
- }
- end
- end
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/emmy-lua.lua b/server-beta/src/core/diagnostics/emmy-lua.lua
deleted file mode 100644
index b3d19c21..00000000
--- a/server-beta/src/core/diagnostics/emmy-lua.lua
+++ /dev/null
@@ -1,3 +0,0 @@
-return function ()
-
-end
diff --git a/server-beta/src/core/diagnostics/empty-block.lua b/server-beta/src/core/diagnostics/empty-block.lua
deleted file mode 100644
index 2024f4e3..00000000
--- a/server-beta/src/core/diagnostics/empty-block.lua
+++ /dev/null
@@ -1,49 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-local define = require 'proto.define'
-
--- 检查空代码块
--- 但是排除忙等待(repeat/while)
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- guide.eachSourceType(ast.ast, 'if', function (source)
- for _, block in ipairs(source) do
- if #block > 0 then
- return
- end
- end
- callback {
- start = source.start,
- finish = source.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script.DIAG_EMPTY_BLOCK,
- }
- end)
- guide.eachSourceType(ast.ast, 'loop', function (source)
- if #source > 0 then
- return
- end
- callback {
- start = source.start,
- finish = source.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script.DIAG_EMPTY_BLOCK,
- }
- end)
- guide.eachSourceType(ast.ast, 'in', function (source)
- if #source > 0 then
- return
- end
- callback {
- start = source.start,
- finish = source.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script.DIAG_EMPTY_BLOCK,
- }
- end)
-end
diff --git a/server-beta/src/core/diagnostics/global-in-nil-env.lua b/server-beta/src/core/diagnostics/global-in-nil-env.lua
deleted file mode 100644
index 9a0d4f35..00000000
--- a/server-beta/src/core/diagnostics/global-in-nil-env.lua
+++ /dev/null
@@ -1,66 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-
--- TODO: 检查路径是否可达
-local function mayRun(path)
- return true
-end
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- local root = guide.getRoot(ast.ast)
- local env = guide.getENV(root)
-
- local nilDefs = {}
- if not env.ref then
- return
- end
- for _, ref in ipairs(env.ref) do
- if ref.type == 'setlocal' then
- if ref.value and ref.value.type == 'nil' then
- nilDefs[#nilDefs+1] = ref
- end
- end
- end
-
- if #nilDefs == 0 then
- return
- end
-
- local function check(source)
- local node = source.node
- if node.tag == '_ENV' then
- local ok
- for _, nilDef in ipairs(nilDefs) do
- local mode, pathA = guide.getPath(nilDef, source)
- if mode == 'before'
- and mayRun(pathA) then
- ok = nilDef
- break
- end
- end
- if ok then
- callback {
- start = source.start,
- finish = source.finish,
- uri = uri,
- message = lang.script.DIAG_GLOBAL_IN_NIL_ENV,
- related = {
- {
- start = ok.start,
- finish = ok.finish,
- uri = uri,
- }
- }
- }
- end
- end
- end
-
- guide.eachSourceType(ast.ast, 'getglobal', check)
- guide.eachSourceType(ast.ast, 'setglobal', check)
-end
diff --git a/server-beta/src/core/diagnostics/init.lua b/server-beta/src/core/diagnostics/init.lua
deleted file mode 100644
index 0d523f26..00000000
--- a/server-beta/src/core/diagnostics/init.lua
+++ /dev/null
@@ -1,41 +0,0 @@
-local files = require 'files'
-local define = require 'proto.define'
-local config = require 'config'
-local await = require 'await'
-
-local function check(uri, name, level, results)
- if config.config.diagnostics.disable[name] then
- return
- end
- level = config.config.diagnostics.severity[name] or level
- local severity = define.DiagnosticSeverity[level]
- local clock = os.clock()
- require('core.diagnostics.' .. name)(uri, function (result)
- result.level = severity or result.level
- result.code = name
- results[#results+1] = result
- end, name)
- local passed = os.clock() - clock
- if passed >= 0.5 then
- log.warn(('Diagnostics [%s] @ [%s] takes [%.3f] sec!'):format(name, uri, passed))
- await.delay()
- end
-end
-
-return function (uri)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
- local results = {}
-
- for name, level in pairs(define.DiagnosticDefaultSeverity) do
- check(uri, name, level, results)
- end
-
- if #results == 0 then
- return nil
- end
-
- return results
-end
diff --git a/server-beta/src/core/diagnostics/lowercase-global.lua b/server-beta/src/core/diagnostics/lowercase-global.lua
deleted file mode 100644
index bc48e1e6..00000000
--- a/server-beta/src/core/diagnostics/lowercase-global.lua
+++ /dev/null
@@ -1,39 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-local config = require 'config'
-local library = require 'library'
-
--- 不允许定义首字母小写的全局变量(很可能是拼错或者漏删)
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- local definedGlobal = {}
- for name in pairs(config.config.diagnostics.globals) do
- definedGlobal[name] = true
- end
- for name in pairs(library.global) do
- definedGlobal[name] = true
- end
-
- guide.eachSourceType(ast.ast, 'setglobal', function (source)
- local name = guide.getName(source)
- if definedGlobal[name] then
- return
- end
- local first = name:match '%w'
- if not first then
- return
- end
- if first:match '%l' then
- callback {
- start = source.start,
- finish = source.finish,
- message = lang.script.DIAG_LOWERCASE_GLOBAL,
- }
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/newfield-call.lua b/server-beta/src/core/diagnostics/newfield-call.lua
deleted file mode 100644
index 75681cbc..00000000
--- a/server-beta/src/core/diagnostics/newfield-call.lua
+++ /dev/null
@@ -1,37 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- local lines = files.getLines(uri)
- local text = files.getText(uri)
-
- guide.eachSourceType(ast.ast, 'table', function (source)
- for i = 1, #source do
- local field = source[i]
- if field.type == 'call' then
- local func = field.node
- local args = field.args
- if args then
- local funcLine = guide.positionOf(lines, func.finish)
- local argsLine = guide.positionOf(lines, args.start)
- if argsLine > funcLine then
- callback {
- start = field.start,
- finish = field.finish,
- message = lang.script('DIAG_PREFIELD_CALL'
- , text:sub(func.start, func.finish)
- , text:sub(args.start, args.finish)
- )
- }
- end
- end
- end
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/newline-call.lua b/server-beta/src/core/diagnostics/newline-call.lua
deleted file mode 100644
index cb318380..00000000
--- a/server-beta/src/core/diagnostics/newline-call.lua
+++ /dev/null
@@ -1,38 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- local lines = files.getLines(uri)
-
- guide.eachSourceType(ast.ast, 'call', function (source)
- local node = source.node
- local args = source.args
- if not args then
- return
- end
-
- -- 必须有其他人在继续使用当前对象
- if not source.next then
- return
- end
-
- local nodeRow = guide.positionOf(lines, node.finish)
- local argRow = guide.positionOf(lines, args.start)
- if nodeRow == argRow then
- return
- end
-
- if #args == 1 then
- callback {
- start = args.start,
- finish = args.finish,
- message = lang.script.DIAG_PREVIOUS_CALL,
- }
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/redefined-local.lua b/server-beta/src/core/diagnostics/redefined-local.lua
deleted file mode 100644
index f6176794..00000000
--- a/server-beta/src/core/diagnostics/redefined-local.lua
+++ /dev/null
@@ -1,32 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local lang = require 'language'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- guide.eachSourceType(ast.ast, 'local', function (source)
- local name = source[1]
- if name == '_'
- or name == '_ENV' then
- return
- end
- local exist = guide.getLocal(source, name, source.start-1)
- if exist then
- callback {
- start = source.start,
- finish = source.finish,
- message = lang.script('DIAG_REDEFINED_LOCAL', name),
- related = {
- {
- start = exist.start,
- finish = exist.finish,
- uri = uri,
- }
- },
- }
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/redundant-parameter.lua b/server-beta/src/core/diagnostics/redundant-parameter.lua
deleted file mode 100644
index ec14188e..00000000
--- a/server-beta/src/core/diagnostics/redundant-parameter.lua
+++ /dev/null
@@ -1,102 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local vm = require 'vm'
-local lang = require 'language'
-local define = require 'proto.define'
-local await = require 'await'
-
-local function countLibraryArgs(source)
- local func = vm.getLibrary(source)
- if not func then
- return nil
- end
- local result = 0
- if not func.args then
- return result
- end
- if func.args[#func.args].type == '...' then
- return math.maxinteger
- end
- result = result + #func.args
- return result
-end
-
-local function countCallArgs(source)
- local result = 0
- if not source.args then
- return 0
- end
- if source.node and source.node.type == 'getmethod' then
- result = result + 1
- end
- result = result + #source.args
- return result
-end
-
-local function countFuncArgs(source)
- local result = 0
- if not source.args then
- return result
- end
- if source.args[#source.args].type == '...' then
- return math.maxinteger
- end
- if source.parent and source.parent.type == 'setmethod' then
- result = result + 1
- end
- result = result + #source.args
- return result
-end
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- guide.eachSourceType(ast.ast, 'call', function (source)
- local callArgs = countCallArgs(source)
- if callArgs == 0 then
- return
- end
-
- await.delay(function ()
- return files.globalVersion
- end)
-
- local func = source.node
- local funcArgs
- vm.eachDef(func, function (info)
- if info.mode == 'value' then
- local src = info.source
- if src.type == 'function' then
- local args = countFuncArgs(src)
- if not funcArgs or args > funcArgs then
- funcArgs = args
- end
- end
- end
- end)
-
- funcArgs = funcArgs or countLibraryArgs(func)
- if not funcArgs then
- return
- end
-
- local delta = callArgs - funcArgs
- if delta <= 0 then
- return
- end
- for i = #source.args - delta + 1, #source.args do
- local arg = source.args[i]
- if arg then
- callback {
- start = arg.start,
- finish = arg.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script('DIAG_OVER_MAX_ARGS', funcArgs, callArgs)
- }
- end
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/redundant-value.lua b/server-beta/src/core/diagnostics/redundant-value.lua
deleted file mode 100644
index be483448..00000000
--- a/server-beta/src/core/diagnostics/redundant-value.lua
+++ /dev/null
@@ -1,24 +0,0 @@
-local files = require 'files'
-local define = require 'proto.define'
-local lang = require 'language'
-
-return function (uri, callback, code)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- local diags = ast.diags[code]
- if not diags then
- return
- end
-
- for _, info in ipairs(diags) do
- callback {
- start = info.start,
- finish = info.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script('DIAG_OVER_MAX_VALUES', info.max, info.passed)
- }
- end
-end
diff --git a/server-beta/src/core/diagnostics/trailing-space.lua b/server-beta/src/core/diagnostics/trailing-space.lua
deleted file mode 100644
index e54a6e60..00000000
--- a/server-beta/src/core/diagnostics/trailing-space.lua
+++ /dev/null
@@ -1,55 +0,0 @@
-local files = require 'files'
-local lang = require 'language'
-local guide = require 'parser.guide'
-
-local function isInString(ast, offset)
- local result = false
- guide.eachSourceType(ast, 'string', function (source)
- if offset >= source.start and offset <= source.finish then
- result = true
- end
- end)
- return result
-end
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- local text = files.getText(uri)
- local lines = files.getLines(uri)
- for i = 1, #lines do
- local start = lines[i].start
- local range = lines[i].range
- local lastChar = text:sub(range, range)
- if lastChar ~= ' ' and lastChar ~= '\t' then
- goto NEXT_LINE
- end
- if isInString(ast.ast, range) then
- goto NEXT_LINE
- end
- local first = start
- for n = range - 1, start, -1 do
- local char = text:sub(n, n)
- if char ~= ' ' and char ~= '\t' then
- first = n + 1
- break
- end
- end
- if first == start then
- callback {
- start = first,
- finish = range,
- message = lang.script.DIAG_LINE_ONLY_SPACE,
- }
- else
- callback {
- start = first,
- finish = range,
- message = lang.script.DIAG_LINE_POST_SPACE,
- }
- end
- ::NEXT_LINE::
- end
-end
diff --git a/server-beta/src/core/diagnostics/undefined-env-child.lua b/server-beta/src/core/diagnostics/undefined-env-child.lua
deleted file mode 100644
index df096cb8..00000000
--- a/server-beta/src/core/diagnostics/undefined-env-child.lua
+++ /dev/null
@@ -1,32 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local vm = require 'vm'
-local lang = require 'language'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- -- 再遍历一次 getglobal ,找出 _ENV 被重载的情况
- guide.eachSourceType(ast.ast, 'getglobal', function (source)
- -- 单独验证自己是否在重载过的 _ENV 中有定义
- if source.node.tag == '_ENV' then
- return
- end
- local setInENV = vm.eachRef(source, function (info)
- if info.mode == 'set' then
- return true
- end
- end)
- if setInENV then
- return
- end
- local key = source[1]
- callback {
- start = source.start,
- finish = source.finish,
- message = lang.script('DIAG_UNDEF_ENV_CHILD', key),
- }
- end)
-end
diff --git a/server-beta/src/core/diagnostics/undefined-global.lua b/server-beta/src/core/diagnostics/undefined-global.lua
deleted file mode 100644
index ed81ced3..00000000
--- a/server-beta/src/core/diagnostics/undefined-global.lua
+++ /dev/null
@@ -1,63 +0,0 @@
-local files = require 'files'
-local vm = require 'vm'
-local lang = require 'language'
-local library = require 'library'
-local config = require 'config'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- local globalCache = {}
-
- -- 遍历全局变量,检查所有没有 mode['set'] 的全局变量
- local globals = vm.getGlobals(ast.ast)
- for key, infos in pairs(globals) do
- if infos.mode['set'] == true then
- goto CONTINUE
- end
- if globalCache[key] then
- goto CONTINUE
- end
- local skey = key and key:match '^s|(.+)$'
- if not skey then
- goto CONTINUE
- end
- if library.global[skey] then
- goto CONTINUE
- end
- if config.config.diagnostics.globals[skey] then
- goto CONTINUE
- end
- if globalCache[key] == nil then
- local uris = files.findGlobals(key)
- for i = 1, #uris do
- local destAst = files.getAst(uris[i])
- local destGlobals = vm.getGlobals(destAst.ast)
- if destGlobals[key] and destGlobals[key].mode['set'] then
- globalCache[key] = true
- goto CONTINUE
- end
- end
- end
- globalCache[key] = false
- local message = lang.script('DIAG_UNDEF_GLOBAL', skey)
- local otherVersion = library.other[skey]
- local customVersion = library.custom[skey]
- if otherVersion then
- message = ('%s(%s)'):format(message, lang.script('DIAG_DEFINED_VERSION', table.concat(otherVersion, '/'), config.config.runtime.version))
- elseif customVersion then
- message = ('%s(%s)'):format(message, lang.script('DIAG_DEFINED_CUSTOM', table.concat(customVersion, '/')))
- end
- for _, info in ipairs(infos) do
- callback {
- start = info.source.start,
- finish = info.source.finish,
- message = message,
- }
- end
- ::CONTINUE::
- end
-end
diff --git a/server-beta/src/core/diagnostics/unused-function.lua b/server-beta/src/core/diagnostics/unused-function.lua
deleted file mode 100644
index 6c53cdf7..00000000
--- a/server-beta/src/core/diagnostics/unused-function.lua
+++ /dev/null
@@ -1,45 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local vm = require 'vm'
-local define = require 'proto.define'
-local lang = require 'language'
-local await = require 'await'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- -- 只检查局部函数与全局函数
- guide.eachSourceType(ast.ast, 'function', function (source)
- local parent = source.parent
- if not parent then
- return
- end
- if parent.type ~= 'local'
- and parent.type ~= 'setlocal'
- and parent.type ~= 'setglobal' then
- return
- end
- local hasSet
- local hasGet = vm.eachRef(source, function (info)
- if info.mode == 'get' then
- return true
- elseif info.mode == 'set'
- or info.mode == 'declare' then
- hasSet = true
- end
- end)
- if not hasGet and hasSet then
- callback {
- start = source.start,
- finish = source.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script.DIAG_UNUSED_FUNCTION,
- }
- end
- await.delay(function ()
- return files.globalVersion
- end)
- end)
-end
diff --git a/server-beta/src/core/diagnostics/unused-label.lua b/server-beta/src/core/diagnostics/unused-label.lua
deleted file mode 100644
index e6d998ba..00000000
--- a/server-beta/src/core/diagnostics/unused-label.lua
+++ /dev/null
@@ -1,22 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local define = require 'proto.define'
-local lang = require 'language'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- guide.eachSourceType(ast.ast, 'label', function (source)
- if not source.ref then
- callback {
- start = source.start,
- finish = source.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script('DIAG_UNUSED_LABEL', source[1]),
- }
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/unused-local.lua b/server-beta/src/core/diagnostics/unused-local.lua
deleted file mode 100644
index 22b2e16b..00000000
--- a/server-beta/src/core/diagnostics/unused-local.lua
+++ /dev/null
@@ -1,46 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local define = require 'proto.define'
-local lang = require 'language'
-
-local function hasGet(loc)
- if not loc.ref then
- return false
- end
- for _, ref in ipairs(loc.ref) do
- if ref.type == 'getlocal' then
- if not ref.next then
- return true
- end
- local nextType = ref.next.type
- if nextType ~= 'setmethod'
- and nextType ~= 'setfield'
- and nextType ~= 'setindex' then
- return true
- end
- end
- end
- return false
-end
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
- guide.eachSourceType(ast.ast, 'local', function (source)
- local name = source[1]
- if name == '_'
- or name == '_ENV' then
- return
- end
- if not hasGet(source) then
- callback {
- start = source.start,
- finish = source.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script('DIAG_UNUSED_LOCAL', name),
- }
- end
- end)
-end
diff --git a/server-beta/src/core/diagnostics/unused-vararg.lua b/server-beta/src/core/diagnostics/unused-vararg.lua
deleted file mode 100644
index 74cc08e7..00000000
--- a/server-beta/src/core/diagnostics/unused-vararg.lua
+++ /dev/null
@@ -1,31 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local define = require 'proto.define'
-local lang = require 'language'
-
-return function (uri, callback)
- local ast = files.getAst(uri)
- if not ast then
- return
- end
-
- guide.eachSourceType(ast.ast, 'function', function (source)
- local args = source.args
- if not args then
- return
- end
-
- for _, arg in ipairs(args) do
- if arg.type == '...' then
- if not arg.ref then
- callback {
- start = arg.start,
- finish = arg.finish,
- tags = { define.DiagnosticTag.Unnecessary },
- message = lang.script.DIAG_UNUSED_VARARG,
- }
- end
- end
- end
- end)
-end
diff --git a/server-beta/src/core/highlight.lua b/server-beta/src/core/highlight.lua
deleted file mode 100644
index 61e3f91a..00000000
--- a/server-beta/src/core/highlight.lua
+++ /dev/null
@@ -1,230 +0,0 @@
-local guide = require 'parser.guide'
-local files = require 'files'
-local vm = require 'vm'
-local define = require 'proto.define'
-
-local function ofLocal(source, callback)
- callback(source)
- if source.ref then
- for _, ref in ipairs(source.ref) do
- callback(ref)
- end
- end
-end
-
-local function ofField(source, uri, callback)
- local parent = source.parent
- if not parent then
- return
- end
- local myKey = guide.getKeyName(source)
- if parent.type == 'tableindex'
- or parent.type == 'tablefield' then
- local tbl = parent.parent
- vm.eachField(tbl, function (info)
- if info.key ~= myKey then
- return
- end
- local destUri = guide.getRoot(info.source).uri
- if destUri ~= uri then
- return
- end
- callback(info.source)
- end)
- else
- vm.eachField(parent.node, function (info)
- if info.key ~= myKey then
- return
- end
- local destUri = guide.getRoot(info.source).uri
- if destUri ~= uri then
- return
- end
- callback(info.source)
- end)
- end
-end
-
-local function ofIndex(source, uri, callback)
- local parent = source.parent
- if not parent then
- return
- end
- if parent.type == 'setindex'
- or parent.type == 'getindex'
- or parent.type == 'tableindex' then
- ofField(source, uri, callback)
- end
-end
-
-local function ofLabel(source, callback)
- vm.eachRef(source, function (info)
- callback(info.source)
- end)
-end
-
-local function find(source, uri, callback)
- if source.type == 'local' then
- ofLocal(source, callback)
- elseif source.type == 'getlocal'
- or source.type == 'setlocal' then
- ofLocal(source.node, callback)
- elseif source.type == 'field'
- or source.type == 'method' then
- ofField(source, uri, callback)
- elseif source.type == 'string'
- or source.type == 'boolean'
- or source.type == 'number' then
- ofIndex(source, uri, callback)
- callback(source)
- elseif source.type == 'nil' then
- callback(source)
- elseif source.type == 'goto'
- or source.type == 'label' then
- ofLabel(source, callback)
- end
-end
-
-local function checkInIf(source, text, offset)
- -- 检查 end
- local endA = source.finish - #'end' + 1
- local endB = source.finish
- if offset >= endA
- and offset <= endB
- and text:sub(endA, endB) == 'end' then
- return true
- end
- -- 检查每个子模块
- for _, block in ipairs(source) do
- for i = 1, #block.keyword, 2 do
- local start = block.keyword[i]
- local finish = block.keyword[i+1]
- if offset >= start and offset <= finish then
- return true
- end
- end
- end
- return false
-end
-
-local function makeIf(source, text, callback)
- -- end
- local endA = source.finish - #'end' + 1
- local endB = source.finish
- if text:sub(endA, endB) == 'end' then
- callback(endA, endB)
- end
- -- 每个子模块
- for _, block in ipairs(source) do
- for i = 1, #block.keyword, 2 do
- local start = block.keyword[i]
- local finish = block.keyword[i+1]
- callback(start, finish)
- end
- end
- return false
-end
-
-local function findKeyword(source, text, offset, callback)
- if source.type == 'do'
- or source.type == 'function'
- or source.type == 'loop'
- or source.type == 'in'
- or source.type == 'while'
- or source.type == 'repeat' then
- local ok
- for i = 1, #source.keyword, 2 do
- local start = source.keyword[i]
- local finish = source.keyword[i+1]
- if offset >= start and offset <= finish then
- ok = true
- break
- end
- end
- if ok then
- for i = 1, #source.keyword, 2 do
- local start = source.keyword[i]
- local finish = source.keyword[i+1]
- callback(start, finish)
- end
- end
- elseif source.type == 'if' then
- local ok = checkInIf(source, text, offset)
- if ok then
- makeIf(source, text, callback)
- end
- end
-end
-
-return function (uri, offset)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
- local text = files.getText(uri)
- local results = {}
- local mark = {}
- guide.eachSourceContain(ast.ast, offset, function (source)
- find(source, uri, function (target)
- local kind
- if target.type == 'getfield' then
- target = target.field
- kind = define.DocumentHighlightKind.Read
- elseif target.type == 'setfield'
- or target.type == 'tablefield' then
- target = target.field
- kind = define.DocumentHighlightKind.Write
- elseif target.type == 'getmethod' then
- target = target.method
- kind = define.DocumentHighlightKind.Read
- elseif target.type == 'setmethod' then
- target = target.method
- kind = define.DocumentHighlightKind.Write
- elseif target.type == 'getindex' then
- target = target.index
- kind = define.DocumentHighlightKind.Read
- elseif target.type == 'setindex'
- or target.type == 'tableindex' then
- target = target.index
- kind = define.DocumentHighlightKind.Write
- elseif target.type == 'getlocal'
- or target.type == 'getglobal'
- or target.type == 'goto' then
- kind = define.DocumentHighlightKind.Read
- elseif target.type == 'setlocal'
- or target.type == 'local'
- or target.type == 'setglobal'
- or target.type == 'label' then
- kind = define.DocumentHighlightKind.Write
- elseif target.type == 'string'
- or target.type == 'boolean'
- or target.type == 'number'
- or target.type == 'nil' then
- kind = define.DocumentHighlightKind.Text
- else
- log.warn('Unknow target.type:', target.type)
- return
- end
- if mark[target] then
- return
- end
- mark[target] = true
- results[#results+1] = {
- start = target.start,
- finish = target.finish,
- kind = kind,
- }
- end)
- findKeyword(source, text, offset, function (start, finish)
- results[#results+1] = {
- start = start,
- finish = finish,
- kind = define.DocumentHighlightKind.Write
- }
- end)
- end)
- if #results == 0 then
- return nil
- end
- return results
-end
diff --git a/server-beta/src/core/hover/arg.lua b/server-beta/src/core/hover/arg.lua
deleted file mode 100644
index be344488..00000000
--- a/server-beta/src/core/hover/arg.lua
+++ /dev/null
@@ -1,20 +0,0 @@
-local guide = require 'parser.guide'
-local vm = require 'vm'
-
-local function asFunction(source)
- if not source.args then
- return ''
- end
- local args = {}
- for i = 1, #source.args do
- local arg = source.args[i]
- args[i] = ('%s: %s'):format(guide.getName(arg), vm.getType(arg))
- end
- return table.concat(args, ', ')
-end
-
-return function (source)
- if source.type == 'function' then
- return asFunction(source)
- end
-end
diff --git a/server-beta/src/core/hover/init.lua b/server-beta/src/core/hover/init.lua
deleted file mode 100644
index b99c14b2..00000000
--- a/server-beta/src/core/hover/init.lua
+++ /dev/null
@@ -1,56 +0,0 @@
-local files = require 'files'
-local guide = require 'parser.guide'
-local vm = require 'vm'
-local getLabel = require 'core.hover.label'
-
-local function getHoverAsFunction(source)
- local values = vm.getValue(source)
- local labels = {}
- for _, value in ipairs(values) do
- if value.type == 'function' then
- labels[#labels+1] = getLabel(value.source)
- end
- end
-
- local label = table.concat(labels, '\n')
- return {
- label = label,
- source = source,
- }
-end
-
-local function getHoverAsValue(source)
- local label = getLabel(source)
- return {
- label = label,
- source = source,
- }
-end
-
-local function getHover(source)
- local isFunction = vm.hasType(source, 'function')
- if isFunction then
- return getHoverAsFunction(source)
- else
- return getHoverAsValue(source)
- end
-end
-
-return function (uri, offset)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
- local hover = guide.eachSourceContain(ast.ast, offset, function (source)
- if source.type == 'local'
- or source.type == 'setlocal'
- or source.type == 'getlocal'
- or source.type == 'setglobal'
- or source.type == 'getglobal'
- or source.type == 'field'
- or source.type == 'method' then
- return getHover(source)
- end
- end)
- return hover
-end
diff --git a/server-beta/src/core/hover/label.lua b/server-beta/src/core/hover/label.lua
deleted file mode 100644
index 72ce60f4..00000000
--- a/server-beta/src/core/hover/label.lua
+++ /dev/null
@@ -1,103 +0,0 @@
-local buildName = require 'core.hover.name'
-local buildArg = require 'core.hover.arg'
-local buildReturn = require 'core.hover.return'
-local buildTable = require 'core.hover.table'
-local vm = require 'vm'
-local util = require 'utility'
-
-local function asFunction(source)
- local name = buildName(source)
- local arg = buildArg(source)
- local rtn = buildReturn(source)
- local lines = {}
- lines[1] = ('function %s(%s)'):format(name, arg)
- lines[2] = rtn
- return table.concat(lines, '\n')
-end
-
-local function asLocal(source)
- local name = buildName(source)
- local type = vm.getType(source)
- local literal = vm.getLiteral(source)
- if type == 'table' then
- type = buildTable(source)
- end
- if literal == nil then
- return ('local %s: %s'):format(name, type)
- else
- return ('local %s: %s = %s'):format(name, type, util.viewLiteral(literal))
- end
-end
-
-local function asGlobal(source)
- local name = buildName(source)
- local type = vm.getType(source)
- local literal = vm.getLiteral(source)
- if type == 'table' then
- type = buildTable(source)
- end
- if literal == nil then
- return ('global %s: %s'):format(name, type)
- else
- return ('global %s: %s = %s'):format(name, type, util.viewLiteral(literal))
- end
-end
-
-local function isGlobalField(source)
- if source.type == 'field'
- or source.type == 'method' then
- source = source.parent
- end
- if source.type == 'setfield'
- or source.type == 'getfield'
- or source.type == 'setmethod'
- or source.type == 'getmethod'
- or source.type == 'tablefield' then
- local node = source.node
- if node.type == 'setglobal'
- or node.type == 'getglobal' then
- return true
- end
- return isGlobalField(node)
- else
- return false
- end
-end
-
-local function asField(source)
- if isGlobalField(source) then
- return asGlobal(source)
- end
- local name = buildName(source)
- local type = vm.getType(source)
- local literal = vm.getLiteral(source)
- if type == 'table' then
- type = buildTable(source)
- end
- if literal == nil then
- return ('field %s: %s'):format(name, type)
- else
- return ('field %s: %s = %s'):format(name, type, util.viewLiteral(literal))
- end
-end
-
-return function (source)
- if source.type == 'function' then
- return asFunction(source)
- elseif source.type == 'local'
- or source.type == 'getlocal'
- or source.type == 'setlocal' then
- return asLocal(source)
- elseif source.type == 'setglobal'
- or source.type == 'getglobal' then
- return asGlobal(source)
- elseif source.type == 'getfield'
- or source.type == 'setfield'
- or source.type == 'getmethod'
- or source.type == 'setmethod'
- or source.type == 'tablefield'
- or source.type == 'field'
- or source.type == 'method' then
- return asField(source)
- end
-end
diff --git a/server-beta/src/core/hover/name.lua b/server-beta/src/core/hover/name.lua
deleted file mode 100644
index a22a8b5a..00000000
--- a/server-beta/src/core/hover/name.lua
+++ /dev/null
@@ -1,64 +0,0 @@
-local guide = require 'parser.guide'
-local vm = require 'vm'
-
-local function asLocal(source)
- return guide.getName(source)
-end
-
-local function asMethod(source)
- local class = vm.eachField(source.node, function (info)
- if info.key == 's|type' or info.key == 's|__name' or info.key == 's|name' then
- if info.value and info.value.type == 'string' then
- return info.value[1]
- end
- end
- end)
- local node = class or guide.getName(source.node) or '?'
- local method = guide.getName(source)
- return ('%s:%s'):format(node, method)
-end
-
-local function asField(source)
- local class = vm.eachField(source.node, function (info)
- if info.key == 's|type' or info.key == 's|__name' or info.key == 's|name' then
- if info.value and info.value.type == 'string' then
- return info.value[1]
- end
- end
- end)
- local node = class or guide.getName(source.node) or '?'
- local method = guide.getName(source)
- return ('%s.%s'):format(node, method)
-end
-
-local function asGlobal(source)
- return guide.getName(source)
-end
-
-local function buildName(source)
- if source.type == 'local'
- or source.type == 'getlocal'
- or source.type == 'setlocal' then
- return asLocal(source) or ''
- end
- if source.type == 'setglobal'
- or source.type == 'getglobal' then
- return asGlobal(source) or ''
- end
- if source.type == 'setmethod'
- or source.type == 'getmethod' then
- return asMethod(source) or ''
- end
- if source.type == 'setfield'
- or source.tyoe == 'getfield'
- or source.type == 'tablefield' then
- return asField(source) or ''
- end
- local parent = source.parent
- if parent then
- return buildName(parent)
- end
- return ''
-end
-
-return buildName
diff --git a/server-beta/src/core/hover/return.lua b/server-beta/src/core/hover/return.lua
deleted file mode 100644
index c22626a6..00000000
--- a/server-beta/src/core/hover/return.lua
+++ /dev/null
@@ -1,34 +0,0 @@
-local guide = require 'parser.guide'
-local vm = require 'vm'
-
-local function asFunction(source)
- if not source.returns then
- return nil
- end
- local returns = {}
- for _, rtn in ipairs(source.returns) do
- for i = 1, #rtn do
- local values = vm.getValue(rtn[i])
- returns[#returns+1] = values
- end
- break
- end
- if #returns == 0 then
- return nil
- end
- local lines = {}
- for i = 1, #returns do
- if i == 1 then
- lines[i] = (' -> %s'):format(vm.viewType(returns[i]))
- else
- lines[i] = ('% 3d. %s'):format(i, returns[i])
- end
- end
- return table.concat(lines, '\n')
-end
-
-return function (source)
- if source.type == 'function' then
- return asFunction(source)
- end
-end
diff --git a/server-beta/src/core/hover/table.lua b/server-beta/src/core/hover/table.lua
deleted file mode 100644
index 9ed86692..00000000
--- a/server-beta/src/core/hover/table.lua
+++ /dev/null
@@ -1,35 +0,0 @@
-local vm = require 'vm'
-
-local function checkClass(source)
-end
-
-return function (source)
- local fields = {}
- local class
- vm.eachField(source, function (info)
- if info.key == 's|type' or info.key == 's|__name' or info.key == 's|name' then
- if info.value and info.value.type == 'string' then
- class = info.value[1]
- end
- end
- local type = vm.getType(info.source)
- fields[#fields+1] = ('%s'):format(type)
- end)
- local fieldsBuf
- if #fields == 0 then
- fieldsBuf = '{}'
- else
- local lines = {}
- lines[#lines+1] = '{'
- for _, field in ipairs(fields) do
- lines[#lines+1] = ' ' .. field
- end
- lines[#lines+1] = '}'
- fieldsBuf = table.concat(lines, '\n')
- end
- if class then
- return ('%s %s'):format(class, fieldsBuf)
- else
- return fieldsBuf
- end
-end
diff --git a/server-beta/src/core/reference.lua b/server-beta/src/core/reference.lua
deleted file mode 100644
index 7e265e97..00000000
--- a/server-beta/src/core/reference.lua
+++ /dev/null
@@ -1,84 +0,0 @@
-local guide = require 'parser.guide'
-local files = require 'files'
-local vm = require 'vm'
-
-local function isFunction(source, offset)
- if source.type ~= 'function' then
- return false
- end
- -- 必须点在 `function` 这个单词上才能查找函数引用
- return offset >= source.start and offset < source.start + #'function'
-end
-
-local function findRef(source, offset, callback)
- if source.type ~= 'local'
- and source.type ~= 'getlocal'
- and source.type ~= 'setlocal'
- and source.type ~= 'setglobal'
- and source.type ~= 'getglobal'
- and source.type ~= 'field'
- and source.type ~= 'tablefield'
- and source.type ~= 'method'
- and source.type ~= 'string'
- and source.type ~= 'number'
- and source.type ~= 'boolean'
- and source.type ~= 'goto'
- and source.type ~= 'label'
- and not isFunction(source, offset) then
- return
- end
- vm.eachRef(source, function (info)
- if info.mode == 'declare'
- or info.mode == 'set'
- or info.mode == 'get'
- or info.mode == 'return' then
- local src = info.source
- local root = guide.getRoot(src)
- local uri = root.uri
- if src.type == 'setfield'
- or src.type == 'getfield'
- or src.type == 'tablefield' then
- callback(src.field, uri)
- elseif src.type == 'setindex'
- or src.type == 'getindex'
- or src.type == 'tableindex' then
- callback(src.index, uri)
- elseif src.type == 'getmethod'
- or src.type == 'setmethod' then
- callback(src.method, uri)
- else
- callback(src, uri)
- end
- end
- if info.mode == 'value' then
- local src = info.source
- local root = guide.getRoot(src)
- local uri = root.uri
- if src.type == 'function' then
- if src.parent.type == 'return' then
- callback(src, uri)
- end
- end
- end
- end)
-end
-
-return function (uri, offset)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
- local results = {}
- guide.eachSourceContain(ast.ast, offset, function (source)
- findRef(source, offset, function (target, uri)
- results[#results+1] = {
- target = target,
- uri = files.getOriginUri(uri),
- }
- end)
- end)
- if #results == 0 then
- return nil
- end
- return results
-end
diff --git a/server-beta/src/core/rename.lua b/server-beta/src/core/rename.lua
deleted file mode 100644
index 3e4512da..00000000
--- a/server-beta/src/core/rename.lua
+++ /dev/null
@@ -1,374 +0,0 @@
-local files = require 'files'
-local vm = require 'vm'
-local guide = require 'parser.guide'
-local proto = require 'proto'
-local define = require 'proto.define'
-local util = require 'utility'
-
-local Forcing
-
-local function askForcing(str)
- if TEST then
- return true
- end
- if Forcing == false then
- return false
- end
- local version = files.globalVersion
- -- TODO
- local item = proto.awaitRequest('window/showMessageRequest', {
- type = define.MessageType.Warning,
- message = ('[%s]不是有效的标识符,是否强制替换?'):format(str),
- actions = {
- {
- title = '强制替换',
- },
- {
- title = '取消',
- },
- }
- })
- if version ~= files.globalVersion then
- Forcing = false
- proto.notify('window/showMessage', {
- type = define.MessageType.Warning,
- message = '文件发生了变化,替换取消。'
- })
- return false
- end
- if not item then
- Forcing = false
- return false
- end
- if item.title == '强制替换' then
- Forcing = true
- return true
- else
- Forcing = false
- return false
- end
-end
-
-local function askForMultiChange(results, newname)
- if TEST then
- return true
- end
- local uris = {}
- for _, result in ipairs(results) do
- local uri = result.uri
- if not uris[uri] then
- uris[uri] = 0
- uris[#uris+1] = uri
- end
- uris[uri] = uris[uri] + 1
- end
- if #uris <= 1 then
- return true
- end
-
- local version = files.globalVersion
- -- TODO
- local item = proto.awaitRequest('window/showMessageRequest', {
- type = define.MessageType.Warning,
- message = ('将修改 %d 个文件,共 %d 处。'):format(
- #uris,
- #results
- ),
- actions = {
- {
- title = '继续',
- },
- {
- title = '放弃',
- },
- }
- })
- if version ~= files.globalVersion then
- proto.notify('window/showMessage', {
- type = define.MessageType.Warning,
- message = '文件发生了变化,替换取消。'
- })
- return false
- end
- if item and item.title == '继续' then
- local fileList = {}
- for _, uri in ipairs(uris) do
- fileList[#fileList+1] = ('%s (%d)'):format(uri, uris[uri])
- end
-
- log.debug(('Renamed [%s]\r\n%s'):format(newname, table.concat(fileList, '\r\n')))
- return true
- end
- return false
-end
-
-local function trim(str)
- return str:match '^%s*(%S+)%s*$'
-end
-
-local function isValidName(str)
- return str:match '^[%a_][%w_]*$'
-end
-
-local function isValidGlobal(str)
- for s in str:gmatch '[^%.]*' do
- if not isValidName(trim(s)) then
- return false
- end
- end
- return true
-end
-
-local function isValidFunctionName(str)
- if isValidGlobal(str) then
- return true
- end
- local pos = str:find(':', 1, true)
- if not pos then
- return false
- end
- return isValidGlobal(trim(str:sub(1, pos-1)))
- and isValidName(trim(str:sub(pos+1)))
-end
-
-local function isFunctionGlobalName(source)
- local parent = source.parent
- if parent.type ~= 'setglobal' then
- return false
- end
- local value = parent.value
- if not value.type ~= 'function' then
- return false
- end
- return value.start <= parent.start
-end
-
-local function renameLocal(source, newname, callback)
- if isValidName(newname) then
- callback(source, source.start, source.finish, newname)
- return
- end
- if askForcing(newname) then
- callback(source, source.start, source.finish, newname)
- end
-end
-
-local function renameField(source, newname, callback)
- if isValidName(newname) then
- callback(source, source.start, source.finish, newname)
- return true
- end
- local parent = source.parent
- if parent.type == 'setfield'
- or parent.type == 'getfield' then
- local dot = parent.dot
- local newstr = '[' .. util.viewString(newname) .. ']'
- callback(source, dot.start, source.finish, newstr)
- elseif parent.type == 'tablefield' then
- local newstr = '[' .. util.viewString(newname) .. ']'
- callback(source, source.start, source.finish, newstr)
- elseif parent.type == 'getmethod' then
- if not askForcing(newname) then
- return false
- end
- callback(source, source.start, source.finish, newname)
- elseif parent.type == 'setmethod' then
- local uri = guide.getRoot(source).uri
- local text = files.getText(uri)
- local func = parent.value
- -- function mt:name () end --> mt['newname'] = function (self) end
- local newstr = string.format('%s[%s] = function '
- , text:sub(parent.start, parent.node.finish)
- , util.viewString(newname)
- )
- callback(source, func.start, parent.finish, newstr)
- local pl = text:find('(', parent.finish, true)
- if pl then
- if func.args then
- callback(source, pl + 1, pl, 'self, ')
- else
- callback(source, pl + 1, pl, 'self')
- end
- end
- end
- return true
-end
-
-local function renameGlobal(source, newname, callback)
- if isValidGlobal(newname) then
- callback(source, source.start, source.finish, newname)
- return true
- end
- if isValidFunctionName(newname) then
- if not isFunctionGlobalName(source) then
- askForcing(newname)
- end
- callback(source, source.start, source.finish, newname)
- return true
- end
- local newstr = '_ENV[' .. util.viewString(newname) .. ']'
- -- function name () end --> _ENV['newname'] = function () end
- if source.value and source.value.type == 'function'
- and source.value.start < source.start then
- callback(source, source.value.start, source.finish, newstr .. ' = function ')
- return true
- end
- callback(source, source.start, source.finish, newstr)
- return true
-end
-
-local function ofLocal(source, newname, callback)
- renameLocal(source, newname, callback)
- if source.ref then
- for _, ref in ipairs(source.ref) do
- renameLocal(ref, newname, callback)
- end
- end
-end
-
-local function ofField(source, newname, callback)
- return vm.eachRef(source, function (info)
- local src = info.source
- if src.type == 'tablefield'
- or src.type == 'getfield'
- or src.type == 'setfield' then
- src = src.field
- elseif src.type == 'tableindex'
- or src.type == 'getindex'
- or src.type == 'setindex' then
- src = src.index
- elseif src.type == 'getmethod'
- or src.type == 'setmethod' then
- src = src.method
- end
- if src.type == 'string' then
- local quo = src[2]
- local text = util.viewString(newname, quo)
- callback(src, src.start, src.finish, text)
- return
- elseif src.type == 'field'
- or src.type == 'method' then
- local suc = renameField(src, newname, callback)
- if not suc then
- return false
- end
- elseif src.type == 'setglobal'
- or src.type == 'getglobal' then
- local suc = renameGlobal(src, newname, callback)
- if not suc then
- return false
- end
- end
- end)
-end
-
-local function rename(source, newname, callback)
- if source.type == 'label'
- or source.type == 'goto' then
- if not isValidName(newname) and not askForcing(newname)then
- return false
- end
- vm.eachRef(source, function (info)
- callback(info.source, info.source.start, info.source.finish, newname)
- end)
- elseif source.type == 'local' then
- return ofLocal(source, newname, callback)
- elseif source.type == 'setlocal'
- or source.type == 'getlocal' then
- return ofLocal(source.node, newname, callback)
- elseif source.type == 'field'
- or source.type == 'method'
- or source.type == 'tablefield'
- or source.type == 'string'
- or source.type == 'setglobal'
- or source.type == 'getglobal' then
- return ofField(source, newname, callback)
- end
- return true
-end
-
-local function prepareRename(source)
- if source.type == 'label'
- or source.type == 'goto'
- or source.type == 'local'
- or source.type == 'setlocal'
- or source.type == 'getlocal'
- or source.type == 'field'
- or source.type == 'method'
- or source.type == 'tablefield'
- or source.type == 'setglobal'
- or source.type == 'getglobal' then
- return source, source[1]
- elseif source.type == 'string' then
- local parent = source.parent
- if not parent then
- return nil
- end
- if parent.type == 'setindex'
- or parent.type == 'getindex'
- or parent.type == 'tableindex' then
- return source, source[1]
- end
- return nil
- end
- return nil
-end
-
-local m = {}
-
-function m.rename(uri, pos, newname)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
- local results = {}
-
- guide.eachSourceContain(ast.ast, pos, function(source)
- rename(source, newname, function (target, start, finish, text)
- results[#results+1] = {
- start = start,
- finish = finish,
- text = text,
- uri = guide.getRoot(target).uri,
- }
- end)
- end)
-
- if Forcing == false then
- Forcing = nil
- return nil
- end
-
- if #results == 0 then
- return nil
- end
-
- if not askForMultiChange(results, newname) then
- return nil
- end
-
- return results
-end
-
-function m.prepareRename(uri, pos)
- local ast = files.getAst(uri)
- if not ast then
- return nil
- end
-
- local result
- guide.eachSourceContain(ast.ast, pos, function(source)
- local res, text = prepareRename(source)
- if res then
- result = {
- start = source.start,
- finish = source.finish,
- text = text,
- }
- end
- end)
-
- return result
-end
-
-return m