diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/src/matcher/compile.lua | 510 | ||||
-rw-r--r-- | server/src/matcher/definition.lua | 548 | ||||
-rw-r--r-- | server/src/matcher/init.lua | 4 | ||||
-rw-r--r-- | server/src/method/textDocument/definition.lua | 10 | ||||
-rw-r--r-- | server/test/definition/init.lua | 7 |
5 files changed, 541 insertions, 538 deletions
diff --git a/server/src/matcher/compile.lua b/server/src/matcher/compile.lua new file mode 100644 index 00000000..b28c3282 --- /dev/null +++ b/server/src/matcher/compile.lua @@ -0,0 +1,510 @@ +local env = require 'matcher.env' +local mt = {} +mt.__index = mt + +function mt:getVar(key, source) + if key == nil then + return nil + end + local var = self.env.var[key] + or self:getField(self.env.var._ENV, key, source) -- 这里不需要用getVar来递归获取_ENV + if not var then + var = self:addField(self:getVar '_ENV', key, source) + end + if var and var.meta then + var = var.meta + end + return var +end + +function mt:addInfo(obj, type, source) + if not obj then + return nil + end + obj[#obj+1] = { + type = type, + source = source, + } + return obj +end + +function mt:createVar(type, key, source) + local var = { + type = type, + key = key, + source = source, + childs = {}, + } + self.results.vars[#self.results.vars+1] = var + return var +end + +function mt:createLabel(key) + local lbl = { + key = key, + type = 'label', + } + self.results.labels[#self.results.labels+1] = lbl + return lbl +end + +function mt:createDots() + local dots = { + type = 'dots', + } + self.results.dots[#self.results.dots+1] = dots + return dots +end + +function mt:createLocal(key, source, var) + if key == nil then + return nil + end + if not var then + var = self:createVar('local', key, source) + end + self.env.var[key] = var + return var +end + +function mt:addField(parent, key, source) + if parent == nil or key == nil then + return nil + end + assert(source) + local var = parent.childs[key] + if not var then + var = self:createVar('field', key, source) + parent.childs[key] = var + end + return var +end + +function mt:getField(parent, key, source) + if parent == nil or key == nil then + return nil + end + local var + if parent.childs then + var = parent.childs[key] + end + if not var and source then + var = self:addField(parent, key, source) + end + return var +end + +function mt:checkName(name) + local var = self:getVar(name[1], name) + self:addInfo(var, 'get', name) + return var +end + +function mt:checkDots(source) + local dots = self.env.dots + if not dots then + return + end + self:addInfo(dots, 'get', source) +end + +function mt:searchCall(call, simple, i) + local results = {} + for i, exp in ipairs(call) do + results[i] = self:searchExp(exp) + end + + -- 特殊处理 setmetatable + if i == 2 and simple[1][1] == 'setmetatable' then + local obj = results[1] + local metatable = results[2] + if metatable then + local index = self:getField(metatable, '__index') + if obj then + self:setTable(obj, index, 'copy') + return obj + else + return index + end + else + return obj + end + end + return nil +end + +function mt:searchSimple(simple) + local name = simple[1] + local var + if name.type == 'name' then + var = self:getVar(name[1], name) + end + self:searchExp(simple[1]) + for i = 2, #simple do + local obj = simple[i] + local tp = obj.type + if tp == 'call' then + var = self:searchCall(obj, simple, i) + elseif tp == ':' then + elseif tp == 'name' then + if obj.index then + self:checkName(obj) + var = nil + else + var = self:getField(var, obj[1], obj) + if i ~= #simple then + self:addInfo(var, 'get', obj) + end + end + else + if obj.index then + if obj.type == 'string' or obj.type == 'number' or obj.type == 'boolean' then + var = self:getField(var, obj[1], obj) + if i ~= #simple then + self:addInfo(var, 'get', obj) + end + end + else + self:searchExp(obj) + var = nil + end + end + end + return var +end + +function mt:searchBinary(exp) + self:searchExp(exp[1]) + self:searchExp(exp[2]) +end + +function mt:searchUnary(exp) + return self:searchExp(exp[1]) +end + +function mt:searchTable(exp) + local tbl = { + type = 'table', + childs = {}, + } + for _, obj in ipairs(exp) do + if obj.type == 'pair' then + local key, value = obj[1], obj[2] + local res = self:searchExp(value) + local var = self:addField(tbl, key[1], key) + self:setTable(var, res) + self:addInfo(var, 'set', key) + else + self:searchExp(obj) + end + end + return tbl +end + +function mt:searchExp(exp) + local tp = exp.type + if tp == 'nil' then + elseif tp == 'string' then + elseif tp == 'boolean' then + elseif tp == 'number' then + elseif tp == 'name' then + return self:checkName(exp) + elseif tp == 'simple' then + return self:searchSimple(exp) + elseif tp == 'binary' then + self:searchBinary(exp) + elseif tp == 'unary' then + self:searchUnary(exp) + elseif tp == '...' then + self:checkDots(exp) + elseif tp == 'function' then + self:searchFunction(exp) + elseif tp == 'table' then + return self:searchTable(exp) + end + return nil +end + +function mt:searchReturn(action) + for _, exp in ipairs(action) do + self:searchExp(exp) + end +end + +function mt:setTable(var, tbl, mode) + if not var or not tbl then + return + end + if mode == 'copy' then + for k, v in pairs(var.childs) do + if tbl.childs[k] then + for i, info in ipairs(v) do + table.insert(tbl.childs[k], 1, info) + end + end + tbl.childs[k] = v + end + end + var.childs = tbl.childs +end + +function mt:markSimple(simple) + local name = simple[1] + local var = self:getVar(name[1], name) + for i = 2, #simple do + local obj = simple[i] + local tp = obj.type + if tp == ':' then + var = self:createLocal('self', simple[i-1], self:getVar(simple[i-1][1])) + elseif tp == 'name' then + if not obj.index then + var = self:addField(var, obj[1], obj) + if i == #simple then + self:addInfo(var, 'set', obj) + end + else + var = nil + end + else + if obj.index then + var = self:addField(var, obj[1], obj) + if i == #simple then + self:addInfo(var, 'set', obj) + end + else + var = nil + end + end + end + return var +end + +function mt:markSet(simple, tbl) + if simple.type == 'name' then + local var = self:getVar(simple[1], simple) + self:addInfo(var, 'set', simple) + self:setTable(var, tbl) + else + self:searchSimple(simple) + local var = self:markSimple(simple) + self:setTable(var, tbl) + end +end + +function mt:markLocal(name, tbl) + if name.type == 'name' then + local str = name[1] + -- 创建一个局部变量 + local var = self:createLocal(str, name) + self:setTable(var, tbl) + elseif name.type == '...' then + local dots = self:createDots() + self:addInfo(dots, 'local', name) + self.env.dots = dots + elseif name.type == ':' then + -- 创建一个局部变量 + self:createLocal('self', name) + end +end + +function mt:forList(list, callback) + if not list then + return + end + if list.type == 'list' then + for i = 1, #list do + callback(list[i]) + end + else + callback(list) + end +end + +function mt:markSets(action) + local keys = action[1] + local values = action[2] + local results = {} + -- 要先计算赋值 + local i = 0 + self:forList(values, function (value) + i = i + 1 + results[i] = self:searchExp(value) + end) + local i = 0 + self:forList(keys, function (key) + i = i + 1 + self:markSet(key, results[i]) + end) +end + +function mt:markLocals(action) + local keys = action[1] + local values = action[2] + local results = {} + -- 要先计算赋值 + local i = 0 + self:forList(values, function (value) + i = i + 1 + results[i] = self:searchExp(value) + end) + local i = 0 + self:forList(keys, function (key) + i = i + 1 + self:markLocal(key, results[i]) + end) +end + +function mt:searchIfs(action) + for _, block in ipairs(action) do + self.env:push() + if block.filter then + self:searchExp(block.filter) + end + self:searchActions(block) + self.env:pop() + end +end + +function mt:searchLoop(action) + self.env:push() + self:markLocal(action.arg) + self:searchExp(action.min) + self:searchExp(action.max) + if action.step then + self:searchExp(action.step) + end + self:searchActions(action) + self.env:pop() +end + +function mt:searchIn(action) + self:forList(action.exp, function (exp) + self:searchExp(exp) + end) + self.env:push() + self:forList(action.arg, function (arg) + self:markLocal(arg) + end) + self:searchActions(action) + self.env:pop() +end + +function mt:searchDo(action) + self.env:push() + self:searchActions(action) + self.env:pop() +end + +function mt:searchWhile(action) + self:searchExp(action.filter) + self.env:push() + self:searchActions(action) + self.env:pop() +end + +function mt:searchRepeat(action) + self.env:push() + self:searchActions(action) + self:searchExp(action.filter) + self.env:pop() +end + +function mt:searchFunction(func) + self.env:push() + self.env:cut 'dots' + self.env.label = {} + if func.name then + self:markSet(func.name) + end + self:forList(func.arg, function (arg) + self:markLocal(arg) + end) + self:searchActions(func) + self.env:pop() +end + +function mt:searchLocalFunction(func) + self:markLocal(func.name) + self.env:push() + self:forList(func.arg, function (arg) + self:markLocal(arg) + end) + self:searchActions(func) + self.env:pop() +end + +function mt:markLabel(label) + local str = label[1] + if not self.env.label[str] then + self.env.label[str] = self:createLabel(str) + end + self:addInfo(self.env.label[str], 'set', label) +end + +function mt:searchGoTo(obj) + local str = obj[1] + if not self.env.label[str] then + self.env.label[str] = self:createLabel(str) + end + self:addInfo(self.env.label[str], 'goto', obj) +end + +function mt:searchAction(action) + local tp = action.type + if tp == 'do' then + self:searchDo(action) + elseif tp == 'break' then + elseif tp == 'return' then + self:searchReturn(action) + elseif tp == 'label' then + self:markLabel(action) + elseif tp == 'goto' then + self:searchGoTo(action) + elseif tp == 'set' then + self:markSets(action) + elseif tp == 'local' then + self:markLocals(action) + elseif tp == 'simple' then + self:searchSimple(action) + elseif tp == 'if' then + self:searchIfs(action) + elseif tp == 'loop' then + self:searchLoop(action) + elseif tp == 'in' then + self:searchIn(action) + elseif tp == 'while' then + self:searchWhile(action) + elseif tp == 'repeat' then + self:searchRepeat(action) + elseif tp == 'function' then + self:searchFunction(action) + elseif tp == 'localfunction' then + self:searchLocalFunction(action) + end +end + +function mt:searchActions(actions) + for _, action in ipairs(actions) do + self:searchAction(action) + end + return nil +end + +return function (ast) + local searcher = setmetatable({ + env = env { + var = {}, + usable = {} + }, + results = { + labels = {}, + vars = {}, + dots = {}, + } + }, mt) + searcher.env.label = {} + searcher:createLocal('_ENV') + searcher:searchActions(ast) + + return searcher.results +end diff --git a/server/src/matcher/definition.lua b/server/src/matcher/definition.lua index 26a51a4f..41556745 100644 --- a/server/src/matcher/definition.lua +++ b/server/src/matcher/definition.lua @@ -1,503 +1,12 @@ -local env = require 'matcher.env' -local mt = {} -mt.__index = mt -function mt:isContainPos(obj) - return obj.start <= self.pos and obj.finish + 1 >= self.pos +local function isContainPos(obj, pos) + return obj.start <= pos and obj.finish + 1 >= pos end -function mt:getVar(key, source) - if key == nil then - return nil - end - local var = self.env.var[key] - or self:getField(self.env.var._ENV, key, source) -- 这里不需要用getVar来递归获取_ENV - if not var then - var = self:addField(self:getVar '_ENV', key, source) - end - if var and var.meta then - var = var.meta - end - return var -end - -function mt:addInfo(obj, type, source) - if not obj then - return nil - end - obj[#obj+1] = { - type = type, - source = source, - } - return obj -end - -function mt:createVar(type, key, source) - local var = { - type = type, - key = key, - source = source, - childs = {}, - } - self.results.vars[#self.results.vars+1] = var - return var -end - -function mt:createLabel(key) - local lbl = { - key = key, - type = 'label', - } - self.results.labels[#self.results.labels+1] = lbl - return lbl -end - -function mt:createDots() - local dots = { - type = 'dots', - } - self.results.dots[#self.results.dots+1] = dots - return dots -end - -function mt:createLocal(key, source, var) - if key == nil then - return nil - end - if not var then - var = self:createVar('local', key, source) - end - self.env.var[key] = var - return var -end - -function mt:addField(parent, key, source) - if parent == nil or key == nil then - return nil - end - assert(source) - local var = parent.childs[key] - if not var then - var = self:createVar('field', key, source) - parent.childs[key] = var - end - return var -end - -function mt:getField(parent, key, source) - if parent == nil or key == nil then - return nil - end - local var - if parent.childs then - var = parent.childs[key] - end - if not var and source then - var = self:addField(parent, key, source) - end - return var -end - -function mt:checkName(name) - local var = self:getVar(name[1], name) - self:addInfo(var, 'get', name) - return var -end - -function mt:checkDots(source) - local dots = self.env.dots - if not dots then - return - end - self:addInfo(dots, 'get', source) -end - -function mt:searchCall(call, simple, i) - local results = {} - for i, exp in ipairs(call) do - results[i] = self:searchExp(exp) - end - - -- 特殊处理 setmetatable - if i == 2 and simple[1][1] == 'setmetatable' then - local obj = results[1] - local metatable = results[2] - if metatable then - local index = self:getField(metatable, '__index') - if obj then - self:setTable(obj, index, 'copy') - return obj - else - return index - end - else - return obj - end - end - return nil -end - -function mt:searchSimple(simple) - local name = simple[1] - local var - if name.type == 'name' then - var = self:getVar(name[1], name) - end - self:searchExp(simple[1]) - for i = 2, #simple do - local obj = simple[i] - local tp = obj.type - if tp == 'call' then - var = self:searchCall(obj, simple, i) - elseif tp == ':' then - elseif tp == 'name' then - if obj.index then - self:checkName(obj) - var = nil - else - var = self:getField(var, obj[1], obj) - if i ~= #simple then - self:addInfo(var, 'get', obj) - end - end - else - if obj.index then - if obj.type == 'string' or obj.type == 'number' or obj.type == 'boolean' then - var = self:getField(var, obj[1], obj) - if i ~= #simple then - self:addInfo(var, 'get', obj) - end - end - else - self:searchExp(obj) - var = nil - end - end - end - return var -end - -function mt:searchBinary(exp) - self:searchExp(exp[1]) - self:searchExp(exp[2]) -end - -function mt:searchUnary(exp) - return self:searchExp(exp[1]) -end - -function mt:searchTable(exp) - local tbl = { - type = 'table', - childs = {}, - } - for _, obj in ipairs(exp) do - if obj.type == 'pair' then - local key, value = obj[1], obj[2] - local res = self:searchExp(value) - local var = self:addField(tbl, key[1], key) - self:setTable(var, res) - self:addInfo(var, 'set', key) - else - self:searchExp(obj) - end - end - return tbl -end - -function mt:searchExp(exp) - local tp = exp.type - if tp == 'nil' then - elseif tp == 'string' then - elseif tp == 'boolean' then - elseif tp == 'number' then - elseif tp == 'name' then - return self:checkName(exp) - elseif tp == 'simple' then - return self:searchSimple(exp) - elseif tp == 'binary' then - self:searchBinary(exp) - elseif tp == 'unary' then - self:searchUnary(exp) - elseif tp == '...' then - self:checkDots(exp) - elseif tp == 'function' then - self:searchFunction(exp) - elseif tp == 'table' then - return self:searchTable(exp) - end - return nil -end - -function mt:searchReturn(action) - for _, exp in ipairs(action) do - self:searchExp(exp) - end -end - -function mt:setTable(var, tbl, mode) - if not var or not tbl then - return - end - if mode == 'copy' then - for k, v in pairs(var.childs) do - if tbl.childs[k] then - for i, info in ipairs(v) do - table.insert(tbl.childs[k], 1, info) - end - end - tbl.childs[k] = v - end - end - var.childs = tbl.childs -end - -function mt:markSimple(simple) - local name = simple[1] - local var = self:getVar(name[1], name) - for i = 2, #simple do - local obj = simple[i] - local tp = obj.type - if tp == ':' then - var = self:createLocal('self', simple[i-1], self:getVar(simple[i-1][1])) - elseif tp == 'name' then - if not obj.index then - var = self:addField(var, obj[1], obj) - if i == #simple then - self:addInfo(var, 'set', obj) - end - else - var = nil - end - else - if obj.index then - var = self:addField(var, obj[1], obj) - if i == #simple then - self:addInfo(var, 'set', obj) - end - else - var = nil - end - end - end - return var -end - -function mt:markSet(simple, tbl) - if simple.type == 'name' then - local var = self:getVar(simple[1], simple) - self:addInfo(var, 'set', simple) - self:setTable(var, tbl) - else - self:searchSimple(simple) - local var = self:markSimple(simple) - self:setTable(var, tbl) - end -end - -function mt:markLocal(name, tbl) - if name.type == 'name' then - local str = name[1] - -- 创建一个局部变量 - local var = self:createLocal(str, name) - self:setTable(var, tbl) - elseif name.type == '...' then - local dots = self:createDots() - self:addInfo(dots, 'local', name) - self.env.dots = dots - elseif name.type == ':' then - -- 创建一个局部变量 - self:createLocal('self', name) - end -end - -function mt:forList(list, callback) - if not list then - return - end - if list.type == 'list' then - for i = 1, #list do - callback(list[i]) - end - else - callback(list) - end -end - -function mt:markSets(action) - local keys = action[1] - local values = action[2] - local results = {} - -- 要先计算赋值 - local i = 0 - self:forList(values, function (value) - i = i + 1 - results[i] = self:searchExp(value) - end) - local i = 0 - self:forList(keys, function (key) - i = i + 1 - self:markSet(key, results[i]) - end) -end - -function mt:markLocals(action) - local keys = action[1] - local values = action[2] - local results = {} - -- 要先计算赋值 - local i = 0 - self:forList(values, function (value) - i = i + 1 - results[i] = self:searchExp(value) - end) - local i = 0 - self:forList(keys, function (key) - i = i + 1 - self:markLocal(key, results[i]) - end) -end - -function mt:searchIfs(action) - for _, block in ipairs(action) do - self.env:push() - if block.filter then - self:searchExp(block.filter) - end - self:searchActions(block) - self.env:pop() - end -end - -function mt:searchLoop(action) - self.env:push() - self:markLocal(action.arg) - self:searchExp(action.min) - self:searchExp(action.max) - if action.step then - self:searchExp(action.step) - end - self:searchActions(action) - self.env:pop() -end - -function mt:searchIn(action) - self:forList(action.exp, function (exp) - self:searchExp(exp) - end) - self.env:push() - self:forList(action.arg, function (arg) - self:markLocal(arg) - end) - self:searchActions(action) - self.env:pop() -end - -function mt:searchDo(action) - self.env:push() - self:searchActions(action) - self.env:pop() -end - -function mt:searchWhile(action) - self:searchExp(action.filter) - self.env:push() - self:searchActions(action) - self.env:pop() -end - -function mt:searchRepeat(action) - self.env:push() - self:searchActions(action) - self:searchExp(action.filter) - self.env:pop() -end - -function mt:searchFunction(func) - self.env:push() - self.env:cut 'dots' - self.env.label = {} - if func.name then - self:markSet(func.name) - end - self:forList(func.arg, function (arg) - self:markLocal(arg) - end) - self:searchActions(func) - self.env:pop() -end - -function mt:searchLocalFunction(func) - self:markLocal(func.name) - self.env:push() - self:forList(func.arg, function (arg) - self:markLocal(arg) - end) - self:searchActions(func) - self.env:pop() -end - -function mt:markLabel(label) - local str = label[1] - if not self.env.label[str] then - self.env.label[str] = self:createLabel(str) - end - self:addInfo(self.env.label[str], 'set', label) -end - -function mt:searchGoTo(obj) - local str = obj[1] - if not self.env.label[str] then - self.env.label[str] = self:createLabel(str) - end - self:addInfo(self.env.label[str], 'goto', obj) -end - -function mt:searchAction(action) - local tp = action.type - if tp == 'do' then - self:searchDo(action) - elseif tp == 'break' then - elseif tp == 'return' then - self:searchReturn(action) - elseif tp == 'label' then - self:markLabel(action) - elseif tp == 'goto' then - self:searchGoTo(action) - elseif tp == 'set' then - self:markSets(action) - elseif tp == 'local' then - self:markLocals(action) - elseif tp == 'simple' then - self:searchSimple(action) - elseif tp == 'if' then - self:searchIfs(action) - elseif tp == 'loop' then - self:searchLoop(action) - elseif tp == 'in' then - self:searchIn(action) - elseif tp == 'while' then - self:searchWhile(action) - elseif tp == 'repeat' then - self:searchRepeat(action) - elseif tp == 'function' then - self:searchFunction(action) - elseif tp == 'localfunction' then - self:searchLocalFunction(action) - end -end - -function mt:searchActions(actions) - for _, action in ipairs(actions) do - self:searchAction(action) - end - return nil -end - -function mt:definition() - for _, var in ipairs(self.results.vars) do +local function findResult(results, pos) + for _, var in ipairs(results.vars) do for _, info in ipairs(var) do - if self:isContainPos(info.source) then + if isContainPos(info.source, pos) then return { type = 'var', var = var, @@ -505,9 +14,9 @@ function mt:definition() end end end - for _, dots in ipairs(self.results.dots) do + for _, dots in ipairs(results.dots) do for _, info in ipairs(dots) do - if self:isContainPos(info.source) then + if isContainPos(info.source, pos) then return { type = 'dots', dots = dots, @@ -515,9 +24,9 @@ function mt:definition() end end end - for _, label in ipairs(self.results.labels) do + for _, label in ipairs(results.labels) do for _, info in ipairs(label) do - if self:isContainPos(info.source) then + if isContainPos(info.source, pos) then return { type = 'label', label = label, @@ -529,7 +38,7 @@ function mt:definition() end local function parseResult(result) - local results = {} + local positions = {} local tp = result.type if tp == 'var' then local var = result.var @@ -538,11 +47,11 @@ local function parseResult(result) if not source then return false end - results[1] = {source.start, source.finish} + positions[1] = {source.start, source.finish} elseif var.type == 'field' then for _, info in ipairs(var) do if info.type == 'set' then - results[#results+1] = {info.source.start, info.source.finish} + positions[#positions+1] = {info.source.start, info.source.finish} end end else @@ -552,44 +61,27 @@ local function parseResult(result) local dots = result.dots for _, info in ipairs(dots) do if info.type == 'local' then - results[#results+1] = {info.source.start, info.source.finish} + positions[#positions+1] = {info.source.start, info.source.finish} end end elseif tp == 'label' then local label = result.label for _, info in ipairs(label) do if info.type == 'set' then - results[#results+1] = {info.source.start, info.source.finish} + positions[#positions+1] = {info.source.start, info.source.finish} end end else error('unknow result.type:' .. result.type) end - return true, results + return positions end -return function (ast, pos) - local searcher = setmetatable({ - pos = pos, - env = env { - var = {}, - usable = {} - }, - results = { - labels = {}, - vars = {}, - dots = {}, - } - }, mt) - searcher.env.label = {} - searcher:createLocal('_ENV') - searcher:searchActions(ast) - - local result = searcher:definition() - +return function (results, pos) + local result = findResult(results, pos) if not result then - return false + return nil end - - return parseResult(result) + local positions = parseResult(result) + return positions end diff --git a/server/src/matcher/init.lua b/server/src/matcher/init.lua index c570b342..896e5ed7 100644 --- a/server/src/matcher/init.lua +++ b/server/src/matcher/init.lua @@ -1,6 +1,6 @@ local api = { - definition = require 'matcher.definition', - implementation = require 'matcher.implementation', + definition = require 'matcher.definition', + compile = require 'matcher.compile', } return api diff --git a/server/src/method/textDocument/definition.lua b/server/src/method/textDocument/definition.lua index bb8918d6..bcdd6cac 100644 --- a/server/src/method/textDocument/definition.lua +++ b/server/src/method/textDocument/definition.lua @@ -4,20 +4,20 @@ local matcher = require 'matcher' return function (lsp, params) local start_clock = os.clock() local uri = params.textDocument.uri - local ast, lines = lsp:loadText(uri) + local results, lines = lsp:loadText(uri) if not ast then return {} end -- lua是从1开始的,因此都要+1 local position = lines:position(params.position.line + 1, params.position.character + 1, 'utf8') - local suc, results = matcher.definition(ast, position) - if not suc then + local positions = matcher.definition(results, position) + if not positions then return {} end local locations = {} - for i, result in ipairs(results) do - local start, finish = result[1], result[2] + for i, position in ipairs(positions) do + local start, finish = position[1], position[2] local start_row, start_col = lines:rowcol(start, 'utf8') local finish_row, finish_col = lines:rowcol(finish, 'utf8') locations[i] = { diff --git a/server/test/definition/init.lua b/server/test/definition/init.lua index 7d4549a1..435ab2f8 100644 --- a/server/test/definition/init.lua +++ b/server/test/definition/init.lua @@ -45,10 +45,11 @@ function TEST(script) local new_script = script:gsub('<[!?]', ' '):gsub('[!?]>', ' ') local ast, err = parser:ast(new_script) assert(ast) + local results = matcher.compile(ast) + assert(results) - local suc, result = matcher.definition(ast, pos) - if suc then - assert(suc) + local result = matcher.definition(results, pos) + if result then assert(founded(target, result)) else assert(#target == 0) |