summaryrefslogtreecommitdiff
path: root/script-beta/src/core/hover
diff options
context:
space:
mode:
Diffstat (limited to 'script-beta/src/core/hover')
-rw-r--r--script-beta/src/core/hover/arg.lua20
-rw-r--r--script-beta/src/core/hover/init.lua56
-rw-r--r--script-beta/src/core/hover/label.lua103
-rw-r--r--script-beta/src/core/hover/name.lua64
-rw-r--r--script-beta/src/core/hover/return.lua34
-rw-r--r--script-beta/src/core/hover/table.lua35
6 files changed, 312 insertions, 0 deletions
diff --git a/script-beta/src/core/hover/arg.lua b/script-beta/src/core/hover/arg.lua
new file mode 100644
index 00000000..be344488
--- /dev/null
+++ b/script-beta/src/core/hover/arg.lua
@@ -0,0 +1,20 @@
+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/script-beta/src/core/hover/init.lua b/script-beta/src/core/hover/init.lua
new file mode 100644
index 00000000..b99c14b2
--- /dev/null
+++ b/script-beta/src/core/hover/init.lua
@@ -0,0 +1,56 @@
+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/script-beta/src/core/hover/label.lua b/script-beta/src/core/hover/label.lua
new file mode 100644
index 00000000..72ce60f4
--- /dev/null
+++ b/script-beta/src/core/hover/label.lua
@@ -0,0 +1,103 @@
+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/script-beta/src/core/hover/name.lua b/script-beta/src/core/hover/name.lua
new file mode 100644
index 00000000..a22a8b5a
--- /dev/null
+++ b/script-beta/src/core/hover/name.lua
@@ -0,0 +1,64 @@
+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/script-beta/src/core/hover/return.lua b/script-beta/src/core/hover/return.lua
new file mode 100644
index 00000000..c22626a6
--- /dev/null
+++ b/script-beta/src/core/hover/return.lua
@@ -0,0 +1,34 @@
+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/script-beta/src/core/hover/table.lua b/script-beta/src/core/hover/table.lua
new file mode 100644
index 00000000..9ed86692
--- /dev/null
+++ b/script-beta/src/core/hover/table.lua
@@ -0,0 +1,35 @@
+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