diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-04-15 19:10:46 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-04-15 19:10:46 +0800 |
commit | b4524f05ee0a21176cb9a0e22941b04a3eca3773 (patch) | |
tree | b93dcbe480f103866a9ecbeddb614ac8590daacf /script/vm | |
parent | 54e6260b2ac36c4653a30ed5ab5e17d3e7f0abd9 (diff) | |
download | lua-language-server-b4524f05ee0a21176cb9a0e22941b04a3eca3773.zip |
improve performance
Diffstat (limited to 'script/vm')
-rw-r--r-- | script/vm/compiler.lua | 58 | ||||
-rw-r--r-- | script/vm/def.lua | 45 | ||||
-rw-r--r-- | script/vm/field.lua | 2 | ||||
-rw-r--r-- | script/vm/global-manager.lua | 14 | ||||
-rw-r--r-- | script/vm/local-id.lua | 15 | ||||
-rw-r--r-- | script/vm/vm.lua | 2 |
6 files changed, 83 insertions, 53 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 69b1ac25..3840c857 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -18,7 +18,7 @@ local vm = require 'vm.vm' local searchFieldSwitch = util.switch() : case 'table' - : call(function (suri, source, key, pushResult) + : call(function (suri, source, key, ref, pushResult) local hasFiled = false for _, field in ipairs(source) do if field.type == 'tablefield' @@ -52,16 +52,16 @@ local searchFieldSwitch = util.switch() end end) : case 'string' - : call(function (suri, source, key, pushResult) + : call(function (suri, source, key, ref, pushResult) -- change to `string: stringlib` ? local stringlib = globalMgr.getGlobal('type', 'stringlib') if stringlib then - vm.getClassFields(suri, stringlib, key, pushResult) + vm.getClassFields(suri, stringlib, key, ref, pushResult) end end) : case 'local' : case 'self' - : call(function (suri, node, key, pushResult) + : call(function (suri, node, key, ref, pushResult) local fields if key then fields = localID.getSources(node, key) @@ -70,12 +70,14 @@ local searchFieldSwitch = util.switch() end if fields then for _, src in ipairs(fields) do - pushResult(src) + if ref or guide.isSet(src) then + pushResult(src) + end end end end) : case 'doc.type.array' - : call(function (suri, source, key, pushResult) + : call(function (suri, source, key, ref, pushResult) if type(key) == 'number' then if key < 1 or not math.tointeger(key) then @@ -85,7 +87,7 @@ local searchFieldSwitch = util.switch() pushResult(source.node) end) : case 'doc.type.table' - : call(function (suri, source, key, pushResult) + : call(function (suri, source, key, ref, pushResult) for _, field in ipairs(source.fields) do local fieldKey = field.name if fieldKey.type == 'doc.type' then @@ -111,7 +113,7 @@ local searchFieldSwitch = util.switch() end end) : case 'global' - : call(function (suri, node, key, pushResult) + : call(function (suri, node, key, ref, pushResult) if node.cate == 'variable' then if key then if type(key) ~= 'string' then @@ -122,8 +124,10 @@ local searchFieldSwitch = util.switch() for _, set in ipairs(global:getSets(suri)) do pushResult(set) end - for _, get in ipairs(global:getGets(suri)) do - pushResult(get) + if ref then + for _, get in ipairs(global:getGets(suri)) do + pushResult(get) + end end end else @@ -132,17 +136,19 @@ local searchFieldSwitch = util.switch() for _, set in ipairs(global:getSets(suri)) do pushResult(set) end - for _, get in ipairs(global:getGets(suri)) do - pushResult(get) + if ref then + for _, get in ipairs(global:getGets(suri)) do + pushResult(get) + end end end end end if node.cate == 'type' then - vm.getClassFields(suri, node, key, pushResult) + vm.getClassFields(suri, node, key, ref, pushResult) end end) - : default(function (suri, source, key, pushResult) + : default(function (suri, source, key, ref, pushResult) local node = source._globalNode if not node then return @@ -174,12 +180,12 @@ local searchFieldSwitch = util.switch() end end if node.cate == 'type' then - vm.getClassFields(suri, node, key, pushResult) + vm.getClassFields(suri, node, key, ref, pushResult) end end) -function vm.getClassFields(suri, node, key, pushResult) +function vm.getClassFields(suri, node, key, ref, pushResult) local mark = {} local function searchClass(class, searchedFields) @@ -206,7 +212,7 @@ function vm.getClassFields(suri, node, key, pushResult) -- check local field and global field if set.bindSources then for _, src in ipairs(set.bindSources) do - searchFieldSwitch(src.type, suri, src, key, function (field) + searchFieldSwitch(src.type, suri, src, key, ref, function (field) local fieldKey = guide.getKeyName(field) if not searchedFields[fieldKey] and guide.isSet(field) then @@ -215,7 +221,7 @@ function vm.getClassFields(suri, node, key, pushResult) end end) if src.value and src.value.type == 'table' then - searchFieldSwitch('table', suri, src.value, key, function (field) + searchFieldSwitch('table', suri, src.value, key, ref, function (field) local fieldKey = guide.getKeyName(field) if not searchedFields[fieldKey] and guide.isSet(field) then @@ -361,7 +367,7 @@ local function getReturnOfSetMetaTable(args) node:merge(vm.compileNode(tbl)) end if mt then - vm.compileByParentNode(mt, '__index', function (src) + vm.compileByParentNode(mt, '__index', false, function (src) for n in vm.compileNode(src):eachObject() do if n.type == 'global' or n.type == 'local' @@ -529,11 +535,11 @@ end ---@param source vm.node ---@param key? any ---@param pushResult fun(source: parser.object) -function vm.compileByParentNode(source, key, pushResult) +function vm.compileByParentNode(source, key, ref, pushResult) local parentNode = vm.compileNode(source) local suri = guide.getUri(source) for node in parentNode:eachObject() do - searchFieldSwitch(node.type, suri, node, key, pushResult) + searchFieldSwitch(node.type, suri, node, key, ref, pushResult) end end @@ -903,7 +909,7 @@ local compilerSwitch = util.switch() if key == nil then return end - vm.compileByParentNode(source.node, key, function (src) + vm.compileByParentNode(source.node, key, false, function (src) if src.type == 'doc.type.field' or src.type == 'doc.field' then vm.setNode(source, vm.compileNode(src)) @@ -929,7 +935,7 @@ local compilerSwitch = util.switch() vm.setNode(source, value) end else - vm.compileByParentNode(source.node, key, function (src) + vm.compileByParentNode(source.node, key, false, function (src) vm.setNode(source, vm.compileNode(src)) end) end @@ -940,7 +946,7 @@ local compilerSwitch = util.switch() return end local key = guide.getKeyName(source) - vm.compileByParentNode(source.node, key, function (src) + vm.compileByParentNode(source.node, key, false, function (src) if src.type == 'doc.type.field' or src.type == 'doc.field' then vm.setNode(source, vm.compileNode(src)) @@ -953,7 +959,7 @@ local compilerSwitch = util.switch() return end local key = guide.getKeyName(source) - vm.compileByParentNode(source.node, key, function (src) + vm.compileByParentNode(source.node, key, false, function (src) vm.setNode(source, vm.compileNode(src)) end) end) @@ -976,7 +982,7 @@ local compilerSwitch = util.switch() end if not hasMarkDoc then - vm.compileByParentNode(source.parent, guide.getKeyName(source), function (src) + vm.compileByParentNode(source.parent, guide.getKeyName(source), false, function (src) vm.setNode(source, vm.compileNode(src)) end) end diff --git a/script/vm/def.lua b/script/vm/def.lua index 40eb7b90..b66e8fda 100644 --- a/script/vm/def.lua +++ b/script/vm/def.lua @@ -105,7 +105,7 @@ local searchFieldSwitch = util.switch() end end if obj.cate == 'type' then - vm.getClassFields(suri, obj, key, pushResult) + vm.getClassFields(suri, obj, key, false, pushResult) end end) : case 'local' @@ -131,12 +131,11 @@ local searchFieldSwitch = util.switch() end end) -local searchByParentNode -local nodeSwitch = util.switch() +local nodeSwitch;nodeSwitch = util.switch() : case 'field' : case 'method' - : call(function (source, pushResult) - searchByParentNode(source.parent, pushResult) + : call(function (source, lastKey, pushResult) + return nodeSwitch(source.parent.type, source.parent, lastKey, pushResult) end) : case 'getfield' : case 'setfield' @@ -144,23 +143,36 @@ local nodeSwitch = util.switch() : case 'setmethod' : case 'getindex' : case 'setindex' - : call(function (source, pushResult) + : call(function (source, lastKey, pushResult) local parentNode = vm.compileNode(source.node) local uri = guide.getUri(source) local key = guide.getKeyName(source) + if not key then + return + end + if lastKey then + key = key .. vm.ID_SPLITE .. lastKey + end for pn in parentNode:eachObject() do searchFieldSwitch(pn.type, uri, pn, key, pushResult) end + return key, source.node end) : case 'tableindex' : case 'tablefield' - : call(function (source, pushResult) + : call(function (source, lastKey, pushResult) + if lastKey then + return + end local tbl = source.parent local uri = guide.getUri(source) searchFieldSwitch(tbl.type, uri, tbl, guide.getKeyName(source), pushResult) end) : case 'doc.see.field' - : call(function (source, pushResult) + : call(function (source, lastKey, pushResult) + if lastKey then + return + end local parentNode = vm.compileNode(source.parent.name) local uri = guide.getUri(source) for pn in parentNode:eachObject() do @@ -190,8 +202,21 @@ end ---@param source parser.object ---@param pushResult fun(src: parser.object) -function searchByParentNode(source, pushResult) - nodeSwitch(source.type, source, pushResult) +local function searchByParentNode(source, pushResult) + local lastKey + local src = source + while true do + local key, node = nodeSwitch(src.type, src, lastKey, pushResult) + if not key then + break + end + src = node + if lastKey then + lastKey = key .. vm.ID_SPLITE .. lastKey + else + lastKey = key + end + end end local function searchByNode(source, pushResult) diff --git a/script/vm/field.lua b/script/vm/field.lua index 0968df11..ba7cd4c1 100644 --- a/script/vm/field.lua +++ b/script/vm/field.lua @@ -17,7 +17,7 @@ local searchByNodeSwitch = util.switch() local function searchByNode(source, pushResult) local uri = guide.getUri(source) - vm.compileByParentNode(source, nil, function (field) + vm.compileByParentNode(source, nil, true, function (field) searchByNodeSwitch(field.type, uri, field, pushResult) end) end diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua index 9713856e..2a3aea2f 100644 --- a/script/vm/global-manager.lua +++ b/script/vm/global-manager.lua @@ -16,8 +16,6 @@ m.globals = {} ---@type table<uri, table<string, boolean>> m.globalSubs = util.multiTable(2) -m.ID_SPLITE = '\x1F' - local compilerGlobalSwitch = util.switch() : case 'local' : call(function (source) @@ -76,7 +74,7 @@ local compilerGlobalSwitch = util.switch() if parentName == '_G' then name = keyName else - name = ('%s%s%s'):format(parentName, m.ID_SPLITE, keyName) + name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName) end elseif source.node.special == '_G' then name = keyName @@ -104,7 +102,7 @@ local compilerGlobalSwitch = util.switch() if parentName == '_G' then name = keyName else - name = ('%s%s%s'):format(parentName, m.ID_SPLITE, keyName) + name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName) end elseif source.node.special == '_G' then name = keyName @@ -227,7 +225,7 @@ end function m.getGlobal(cate, name, field) local key = cate .. '|' .. name if field then - key = key .. m.ID_SPLITE .. field + key = key .. vm.ID_SPLITE .. field end return m.globals[key] end @@ -244,8 +242,8 @@ function m.getFields(cate, name) for gid, global in pairs(m.globals) do if gid ~= key and util.stringStartWith(gid, key) - and gid:sub(#key + 1, #key + 1) == m.ID_SPLITE - and not gid:find(m.ID_SPLITE, #key + 2) then + and gid:sub(#key + 1, #key + 1) == vm.ID_SPLITE + and not gid:find(vm.ID_SPLITE, #key + 2) then globals[#globals+1] = global end end @@ -266,7 +264,7 @@ function m.getGlobals(cate) local clock = os.clock() for gid, global in pairs(m.globals) do if util.stringStartWith(gid, cate) - and not gid:find(m.ID_SPLITE) then + and not gid:find(vm.ID_SPLITE) then globals[#globals+1] = global end end diff --git a/script/vm/local-id.lua b/script/vm/local-id.lua index aa4f3118..728de301 100644 --- a/script/vm/local-id.lua +++ b/script/vm/local-id.lua @@ -1,5 +1,6 @@ local util = require 'utility' local guide = require 'parser.guide' +local vm = require 'vm.vm' ---@class parser.object ---@field _localID string @@ -8,8 +9,6 @@ local guide = require 'parser.guide' ---@class vm.local-id local m = {} -m.ID_SPLITE = '\x1F' - local compileSwitch = util.switch() : case 'local' : case 'self' @@ -38,7 +37,7 @@ local compileSwitch = util.switch() if type(key) ~= 'string' then return end - source._localID = parentID .. m.ID_SPLITE .. key + source._localID = parentID .. vm.ID_SPLITE .. key source.field._localID = source._localID if source.type == 'getfield' then m.compileLocalID(source.next) @@ -55,7 +54,7 @@ local compileSwitch = util.switch() if type(key) ~= 'string' then return end - source._localID = parentID .. m.ID_SPLITE .. key + source._localID = parentID .. vm.ID_SPLITE .. key source.method._localID = source._localID if source.type == 'getmethod' then m.compileLocalID(source.next) @@ -72,7 +71,7 @@ local compileSwitch = util.switch() if type(key) ~= 'string' then return end - source._localID = parentID .. m.ID_SPLITE .. key + source._localID = parentID .. vm.ID_SPLITE .. key source.index._localID = source._localID if source.type == 'setindex' then m.compileLocalID(source.next) @@ -160,7 +159,7 @@ function m.getSources(source, key) if type(key) ~= 'string' then return nil end - id = id .. m.ID_SPLITE .. key + id = id .. vm.ID_SPLITE .. key end return root._localIDs[id] end @@ -182,9 +181,9 @@ function m.getFields(source) for lid, sources in pairs(root._localIDs) do if lid ~= id and util.stringStartWith(lid, id) - and lid:sub(#id + 1, #id + 1) == m.ID_SPLITE + and lid:sub(#id + 1, #id + 1) == vm.ID_SPLITE -- only one field - and not lid:find(m.ID_SPLITE, #id + 2) then + and not lid:find(vm.ID_SPLITE, #id + 2) then for _, src in ipairs(sources) do fields[#fields+1] = src end diff --git a/script/vm/vm.lua b/script/vm/vm.lua index d370de0d..3c1762bf 100644 --- a/script/vm/vm.lua +++ b/script/vm/vm.lua @@ -14,6 +14,8 @@ _ENV = nil ---@class vm local m = {} +m.ID_SPLITE = '\x1F' + function m.getSpecial(source) if not source then return nil |