diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2020-08-16 15:27:01 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2020-08-16 15:27:01 +0800 |
commit | 8fdeec14b4a90e1f15ed639ebc7b7b423e100424 (patch) | |
tree | 802817ffef749310c5ab9b83fd165ae90ea551f2 /script-beta | |
parent | 36b69f2c7f11e337897d282a10151548cb8876ea (diff) | |
download | lua-language-server-8fdeec14b4a90e1f15ed639ebc7b7b423e100424.zip |
挪到 guide 里
Diffstat (limited to 'script-beta')
-rw-r--r-- | script-beta/core/hover/label.lua | 13 | ||||
-rw-r--r-- | script-beta/core/hover/return.lua | 8 | ||||
-rw-r--r-- | script-beta/core/hover/table.lua | 2 | ||||
-rw-r--r-- | script-beta/parser/guide.lua | 255 | ||||
-rw-r--r-- | script-beta/vm/getClass.lua | 2 | ||||
-rw-r--r-- | script-beta/vm/getValue.lua | 116 | ||||
-rw-r--r-- | script-beta/vm/guideInterface.lua | 2 |
7 files changed, 277 insertions, 121 deletions
diff --git a/script-beta/core/hover/label.lua b/script-beta/core/hover/label.lua index d3fbe6af..5e14c68e 100644 --- a/script-beta/core/hover/label.lua +++ b/script-beta/core/hover/label.lua @@ -4,6 +4,7 @@ local buildReturn = require 'core.hover.return' local buildTable = require 'core.hover.table' local vm = require 'vm' local util = require 'utility' +local guide = require 'parser.guide' local function asFunction(source, oop) local name = buildName(source, oop) @@ -23,11 +24,11 @@ local function asValue(source, title) for _, value in ipairs(values) do local src = value.source local tp = value.type - class = vm.mergeViews(class, vm.getClass(src)) - type = vm.mergeViews(type, tp) + class = guide.mergeInfers(class, vm.getClass(src)) + type = guide.mergeInfers(type, tp) local sl = vm.getLiteral(src) if sl then - literal = vm.mergeViews(literal, util.viewLiteral(sl)) + literal = guide.mergeInfers(literal, util.viewLiteral(sl)) end if tp == 'table' then cont = buildTable(src) @@ -35,11 +36,11 @@ local function asValue(source, title) end end vm.eachDef(source, function (src) - class = vm.mergeViews(class, vm.getClass(src)) - type = vm.mergeViews(type, vm.getType(src)) + class = guide.mergeInfers(class, vm.getClass(src)) + type = guide.mergeInfers(type, vm.getType(src)) local sl = vm.getLiteral(src) if sl then - literal = vm.mergeViews(literal, util.viewLiteral(sl)) + literal = guide.mergeInfers(literal, util.viewLiteral(sl)) end if type == 'table' then cont = buildTable(src) diff --git a/script-beta/core/hover/return.lua b/script-beta/core/hover/return.lua index e6f7a38a..82dc1314 100644 --- a/script-beta/core/hover/return.lua +++ b/script-beta/core/hover/return.lua @@ -21,9 +21,9 @@ local function asLibrary(source) local lines = {} for i = 1, #returns do if i == 1 then - lines[i] = (' -> %s'):format(vm.viewType(returns[i])) + lines[i] = (' -> %s'):format(guide.viewInfer(returns[i])) else - lines[i] = ('% 3d. %s'):format(i, vm.viewType(returns[i])) + lines[i] = ('% 3d. %s'):format(i, guide.viewInfer(returns[i])) end end return table.concat(lines, '\n') @@ -47,9 +47,9 @@ local function asFunction(source) local lines = {} for i = 1, #returns do if i == 1 then - lines[i] = (' -> %s'):format(vm.viewType(returns[i])) + lines[i] = (' -> %s'):format(guide.viewInfer(returns[i])) else - lines[i] = ('% 3d. %s'):format(i, vm.viewType(returns[i])) + lines[i] = ('% 3d. %s'):format(i, guide.viewInfer(returns[i])) end end return table.concat(lines, '\n') diff --git a/script-beta/core/hover/table.lua b/script-beta/core/hover/table.lua index fb89c7f9..d00440a7 100644 --- a/script-beta/core/hover/table.lua +++ b/script-beta/core/hover/table.lua @@ -118,7 +118,7 @@ return function (source) local intValue = true vm.eachField(source, function (src) local key, class, literal = getField(src) - classes[key] = vm.mergeViews(class, classes[key]) + classes[key] = guide.mergeInfers(class, classes[key]) literals[key] = mergeLiteral(literal, literals[key]) if class ~= 'integer' or not literals[key] diff --git a/script-beta/parser/guide.lua b/script-beta/parser/guide.lua index 42ad798b..228b0a61 100644 --- a/script-beta/parser/guide.lua +++ b/script-beta/parser/guide.lua @@ -1,17 +1,23 @@ -local util = require 'utility' -local error = error -local type = type -local next = next -local tostring = tostring -local print = print -local ipairs = ipairs -local tableInsert = table.insert -local tableUnpack = table.unpack -local tableRemove = table.remove -local tableMove = table.move -local pairs = pairs - -_ENV = nil +local util = require 'utility' +local error = error +local type = type +local next = next +local tostring = tostring +local print = print +local ipairs = ipairs +local tableInsert = table.insert +local tableUnpack = table.unpack +local tableRemove = table.remove +local tableMove = table.move +local tableSort = table.sort +local tableConcat = table.concat +local mathType = math.type +local pairs = pairs +local setmetatable = setmetatable +local assert = assert +local select = select + +local _ENV = nil local m = {} @@ -85,6 +91,18 @@ m.actionMap = { ['funcargs'] = {'#'}, } +local TypeSort = { + ['boolean'] = 1, + ['string'] = 2, + ['integer'] = 3, + ['number'] = 4, + ['table'] = 5, + ['function'] = 6, + ['nil'] = 999, +} + +local NIL = setmetatable({'<nil>'}, { __tostring = function () return 'nil' end }) + --- 是否是字面量 function m.isLiteral(obj) local tp = obj.type @@ -1041,6 +1059,9 @@ function m.searchFields(status, obj, key, interface) end function m.getObjectValue(obj) + while obj.type == 'paren' do + obj = obj.exp + end if obj.value then return obj.value end @@ -1823,6 +1844,206 @@ function m.searchRefOfValue(status, obj) end end +function m.mergeInfer(t, b) + if not t then + t = {} + end + if not b then + return t + end + for i = 1, #b do + local o = b[i] + if not t[o] then + t[o] = true + t[#t+1] = o + end + end + return t +end + +function m.allocInfer(o) + -- TODO + assert(o.type) + if type(o.type) == 'table' then + local values = {} + for i = 1, #o.type do + local sub = { + type = o.type[i], + value = o.value, + source = o.source, + } + values[i] = sub + values[sub] = true + end + return values + else + return { + [1] = o, + [o] = true, + } + end +end + +function m.insertInfer(t, o) + if not o then + return + end + if not t[o] then + t[o] = true + t[#t+1] = o + end + return t +end + +local function mergeInfers(types) + if #types == 0 then + return nil + end + if #types == 1 then + return types[1] + end + tableSort(types, function (a, b) + local sa = TypeSort[a] + local sb = TypeSort[b] + if sa and sb then + return sa < sb + end + if not sa and not sb then + return a < b + end + if sa and not sb then + return true + end + if not sa and sb then + return false + end + return false + end) + return tableConcat(types, '|') +end + +function m.mergeInfers(...) + local max = select('#', ...) + local views = {} + for i = 1, max do + local view = select(i, ...) + if view then + for tp in view:gmatch '[^|]+' do + if not views[tp] and tp ~= 'any' then + views[tp] = true + views[#views+1] = tp + end + end + end + end + return mergeInfers(views) +end + +function m.viewInfer(infers) + if not infers then + return 'any' + end + if type(infers) ~= 'table' then + return infers or 'any' + end + local types = {} + for i = 1, #infers do + local tp = infers[i].type + if tp and not types[tp] and tp ~= 'any' then + types[tp] = true + types[#types+1] = tp + end + end + return m.mergeInfers(types) or 'any' +end + +function m.inferCheckLiteral(status, source) + if source.type == 'string' then + return m.alloc { + type = 'string', + value = source[1], + source = source, + } + elseif source.type == 'nil' then + return m.alloc { + type = 'nil', + value = NIL, + source = source, + } + elseif source.type == 'boolean' then + return m.alloc { + type = 'boolean', + value = source[1], + source = source, + } + elseif source.type == 'number' then + if mathType(source[1]) == 'integer' then + return m.alloc { + type = 'integer', + value = source[1], + source = source, + } + else + return m.alloc { + type = 'number', + value = source[1], + source = source, + } + end + elseif source.type == 'integer' then + return m.alloc { + type = 'integer', + source = source, + } + elseif source.type == 'table' then + return m.alloc { + type = 'table', + source = source, + } + elseif source.type == 'function' then + return m.alloc { + type = 'function', + source = source, + } + elseif source.type == '...' then + return m.alloc { + type = '...', + source = source, + } + end +end + +function m.searchInfer(status, obj) + obj = m.getObjectValue(obj) or obj + local results = m.inferCheckLiteral(status, obj) + --or inferCheckUnary(obj) + --or inferCheckBinary(obj) + --or inferCheckLibraryTypes(obj) + --or inferCheckLibrary(obj) + --or inferCheckSpecialReturn(obj) + --or inferCheckLibraryReturn(obj) + if results then + return results + end + + results = {} + --inferByLibraryArg(results, obj) + --inferByDef(results, source) + --inferBySet(results, obj) + --inferByCall(results, obj) + --inferByGetTable(results, obj) + --inferByUnary(results, obj) + --inferByBinary(results, obj) + --inferByCallReturn(results, obj) + --inferByPCallReturn(results, obj) + + if #results == 0 then + return nil + end + + return results +end + --- 请求对象的引用,包括 `a.b.c` 形式 --- 与 `return function` 形式。 --- 不穿透 `setmetatable` ,考虑由 @@ -1857,4 +2078,10 @@ function m.requestFields(obj, interface) return m.searchFields(nil, obj, nil, interface) end +--- 请求对象的类型推测 +function m.requestInfer(obj, interface) + local status = m.status(nil, interface) + return m.searchInfer(status, obj) +end + return m diff --git a/script-beta/vm/getClass.lua b/script-beta/vm/getClass.lua index feccc981..0d5d45b1 100644 --- a/script-beta/vm/getClass.lua +++ b/script-beta/vm/getClass.lua @@ -41,5 +41,5 @@ function vm.getClass(source) if #classes == 0 then return nil end - return vm.mergeViews(table.unpack(classes)) + return guide.mergeInfers(table.unpack(classes)) end diff --git a/script-beta/vm/getValue.lua b/script-beta/vm/getValue.lua index 9837e093..bc83dc10 100644 --- a/script-beta/vm/getValue.lua +++ b/script-beta/vm/getValue.lua @@ -433,19 +433,6 @@ local function checkBinary(source) end end -local function checkValue(source) - if source.value then - return vm.getValue(source.value) - end - if source.type == 'paren' then - return vm.getValue(source.exp) - end - if source.type == 'field' - or source.type == 'method' then - return vm.getValue(source.parent) - end -end - local function inferByCall(results, source) if #results ~= 0 then return @@ -489,7 +476,7 @@ end local function inferByDef(results, source) local defs = vm.getDefs(source) for _, src in ipairs(defs) do - local tp = vm.getValue(src) + local tp = vm.inferValue(src, false) if tp then merge(results, tp) end @@ -812,29 +799,32 @@ local function inferByPCallReturn(results, source) end end -local function getValue(source) +function vm.inferValue(source, infer) + source = guide.getObjectValue(source) or source local results = checkLiteral(source) - --or checkValue(source) - --or checkUnary(source) - --or checkBinary(source) - --or checkLibraryTypes(source) - --or checkLibrary(source) - --or checkSpecialReturn(source) - --or checkLibraryReturn(source) + or checkUnary(source) + or checkBinary(source) + or checkLibraryTypes(source) + or checkLibrary(source) + or checkSpecialReturn(source) + or checkLibraryReturn(source) if results then return results end + if not infer then + return + end results = {} - --inferByLibraryArg(results, source) + inferByLibraryArg(results, source) --inferByDef(results, source) - --inferBySet(results, source) - --inferByCall(results, source) - --inferByGetTable(results, source) - --inferByUnary(results, source) - --inferByBinary(results, source) - --inferByCallReturn(results, source) - --inferByPCallReturn(results, source) + inferBySet(results, source) + inferByCall(results, source) + inferByGetTable(results, source) + inferByUnary(results, source) + inferByBinary(results, source) + inferByCallReturn(results, source) + inferByPCallReturn(results, source) if #results == 0 then return nil @@ -944,71 +934,9 @@ function vm.hasType(source, type) return false end -local function mergeViews(types) - if #types == 0 then - return nil - end - if #types == 1 then - return types[1] - end - table.sort(types, function (a, b) - local sa = typeSort[a] - local sb = typeSort[b] - if sa and sb then - return sa < sb - end - if not sa and not sb then - return a < b - end - if sa and not sb then - return true - end - if not sa and sb then - return false - end - return false - end) - return table.concat(types, '|') -end - -function vm.viewType(values) - if not values then - return 'any' - end - if type(values) ~= 'table' then - return values or 'any' - end - local types = {} - for i = 1, #values do - local tp = values[i].type - if tp and not types[tp] and tp ~= 'any' then - types[tp] = true - types[#types+1] = tp - end - end - return mergeViews(types) or 'any' -end - -function vm.mergeViews(...) - local max = select('#', ...) - local views = {} - for i = 1, max do - local view = select(i, ...) - if view then - for tp in view:gmatch '[^|]+' do - if not views[tp] and tp ~= 'any' then - views[tp] = true - views[#views+1] = tp - end - end - end - end - return mergeViews(views) -end - function vm.getType(source) local values = vm.getValue(source) - return vm.viewType(values) + return guide.viewInfer(values) end --- 获取对象的值 @@ -1025,7 +953,7 @@ function vm.getValue(source) if not unlock then return end - cache = getValue(source) or false + cache = guide.requestInfer(source, vm.interface) or false vm.getCache('getValue')[source] = cache unlock() return cache diff --git a/script-beta/vm/guideInterface.lua b/script-beta/vm/guideInterface.lua index eae22b68..bd7a7c2b 100644 --- a/script-beta/vm/guideInterface.lua +++ b/script-beta/vm/guideInterface.lua @@ -110,7 +110,7 @@ end function vm.setSearchLevel(n) -- 只有在搜索等级由低变高时,才需要清空缓存 if n > vm.interface.searchLevel then - vm.flushCache() + --vm.flushCache() end vm.interface.searchLevel = n end |