diff options
-rw-r--r-- | script-beta/core/definition.lua | 110 | ||||
-rw-r--r-- | script-beta/core/reference.lua | 117 | ||||
-rw-r--r-- | script-beta/parser/guide.lua | 25 | ||||
-rw-r--r-- | script-beta/vm/eachDef.lua | 216 | ||||
-rw-r--r-- | script-beta/vm/eachField.lua | 134 | ||||
-rw-r--r-- | script-beta/vm/eachRef.lua | 221 | ||||
-rw-r--r-- | script-beta/vm/init.lua | 3 | ||||
-rw-r--r-- | test-beta/definition/bug.lua | 14 | ||||
-rw-r--r-- | test-beta/references/init.lua | 133 |
9 files changed, 181 insertions, 792 deletions
diff --git a/script-beta/core/definition.lua b/script-beta/core/definition.lua index ded2fb1c..02383ee6 100644 --- a/script-beta/core/definition.lua +++ b/script-beta/core/definition.lua @@ -3,72 +3,60 @@ 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 (src) - 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) +local accept = { + ['local'] = true, + ['setlocal'] = true, + ['getlocal'] = true, + ['label'] = true, + ['goto'] = true, + ['field'] = true, + ['method'] = true, + ['setindex'] = true, + ['getindex'] = true, + ['tableindex'] = true, + ['setglobal'] = true, + ['getglobal'] = true, +} + +local function findSource(ast, offset) + local len = 999 + local result + guide.eachSourceContain(ast.ast, offset, function (source) + if source.finish - source.start < len and accept[source.type] then + result = source + len = source.finish - source.start end end) + return result end -local function checkRequire(source, offset, callback) +local function checkRequire(source, offset) if source.type ~= 'call' then - return + return nil end local func = source.node local pathSource = source.args and source.args[1] if not pathSource then - return + return nil end if not guide.isContain(pathSource, offset) then - return + return nil end local literal = guide.getLiteral(pathSource) if type(literal) ~= 'string' then - return + return nil end local lib = vm.getLibrary(func) if not lib then - return + return nil end if lib.name == 'require' then - local result = workspace.findUrisByRequirePath(literal, true) - for _, uri in ipairs(result) do - callback(uri) - end + return workspace.findUrisByRequirePath(literal, true) elseif lib.name == 'dofile' or lib.name == 'loadfile' then - local result = workspace.findUrisByFilePath(literal, true) - for _, uri in ipairs(result) do - callback(uri) - end + return workspace.findUrisByFilePath(literal, true) end + return nil end return function (uri, offset) @@ -76,10 +64,17 @@ return function (uri, offset) if not ast then return nil end + + local source = findSource(ast, offset) + if not source then + return nil + end + local results = {} - guide.eachSourceContain(ast.ast, offset, function (source) - checkRequire(source, offset, function (uri) - results[#results+1] = { + local uris = checkRequire(source) + if uris then + for i, uri in ipairs(uris) do + results[#uris+1] = { uri = files.getOriginUri(uri), source = source, target = { @@ -87,15 +82,18 @@ return function (uri, offset) finish = 0, } } - end) - findDef(source, function (target, uri) - results[#results+1] = { - target = target, - uri = files.getOriginUri(uri), - source = source, - } - end) - end) + end + end + + local defs = guide.requestDefinition(source) + for _, src in ipairs(defs) do + results[#results+1] = { + target = src, + uri = files.getOriginUri(uri), + source = source, + } + end + if #results == 0 then return nil end diff --git a/script-beta/core/reference.lua b/script-beta/core/reference.lua index 36d985c0..98872d9c 100644 --- a/script-beta/core/reference.lua +++ b/script-beta/core/reference.lua @@ -1,88 +1,75 @@ 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 +local function isValidFunction(source, offset) -- 必须点在 `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 ~= '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 (src) - 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) +local accept = { + ['local'] = true, + ['setlocal'] = true, + ['getlocal'] = true, + ['label'] = true, + ['goto'] = true, + ['field'] = true, + ['method'] = true, + ['setindex'] = true, + ['getindex'] = true, + ['tableindex'] = true, + ['setglobal'] = true, + ['getglobal'] = true, + ['function'] = true, +} + +local function findSource(ast, offset) + local len = 999 + local result + guide.eachSourceContain(ast.ast, offset, function (source) + if source.finish - source.start < len and accept[source.type] then + result = source + len = source.finish - source.start end end) - vm.eachDef(source, function (src) + if result.type == 'function' and not isValidFunction(result, offset) and not TEST then + return nil + end + return result +end + +return function (uri, offset) + local ast = files.getAst(uri) + if not ast then + return nil + end + + local source = findSource(ast, offset) + if not source then + return nil + end + + local results = {} + local refs = guide.requestReference(source) + for _, src in ipairs(refs) do 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) + src = src.field elseif src.type == 'setindex' or src.type == 'getindex' or src.type == 'tableindex' then - callback(src.index, uri) + src = src.index elseif src.type == 'getmethod' or src.type == 'setmethod' then - callback(src.method, uri) - else - callback(src, uri) + src = src.method end - end) -end - -return function (uri, offset) - local ast = files.getAst(uri) - if not ast then - return nil + results[#results+1] = { + target = src, + uri = files.getOriginUri(root.uri), + } end - local results = {} - local mark = {} - guide.eachSourceContain(ast.ast, offset, function (source) - findRef(source, offset, function (target, uri) - if mark[target] then - return - end - mark[target] = true - results[#results+1] = { - target = target, - uri = files.getOriginUri(uri), - } - end) - end) + if #results == 0 then return nil end diff --git a/script-beta/parser/guide.lua b/script-beta/parser/guide.lua index 76d60a23..033ffde1 100644 --- a/script-beta/parser/guide.lua +++ b/script-beta/parser/guide.lua @@ -1059,6 +1059,7 @@ function m.checkSameSimpleInValueOfSetMetaTable(status, value, start, queue) queue[#queue+1] = { obj = obj, start = start, + force = true, } end if mt then @@ -1090,6 +1091,8 @@ function m.checkSameSimpleInBranch(status, ref, start, queue) m.checkSameSimpleInValueOfSetMetaTable(status, value, start, queue) end + -- 检查自己是字面量表的情况 + m.checkSameSimpleInValueOfTable(status, ref, start, queue) -- 检查自己作为 setmetatable 第一个参数的情况 m.checkSameSimpleInArg1OfSetMetaTable(status, ref, start, queue) end @@ -1240,16 +1243,15 @@ end function m.searchSameFields(status, simple, mode) local first = simple.first local fref = first.ref - if not fref then - return - end local queue = {} - for i = 1, #fref do - local ref = fref[i] - queue[i] = { - obj = ref, - start = 1, - } + if fref then + for i = 1, #fref do + local ref = fref[i] + queue[i] = { + obj = ref, + start = 1, + } + end end if simple.global then for i = 1, #queue do @@ -1421,4 +1423,9 @@ function m.requestDefinition(obj) return status.results end +--- 请求对象的域 +function m.requestFields(obj) + return m.searchFields(nil, obj) +end + return m diff --git a/script-beta/vm/eachDef.lua b/script-beta/vm/eachDef.lua deleted file mode 100644 index 8bb9c0e7..00000000 --- a/script-beta/vm/eachDef.lua +++ /dev/null @@ -1,216 +0,0 @@ -local guide = require 'parser.guide' -local files = require 'files' -local vm = require 'vm.vm' - -local function ofParentMT(func, callback) - if not func or func.type ~= 'function' then - return - end - local parent = func.parent - if not parent or parent.type ~= 'setmethod' then - return - end - local node = parent.node - if not node then - return - end - vm.eachDef(node, callback) -end - -local function ofLocal(loc, callback) - -- 方法中的 self 使用了一个虚拟的定义位置 - if loc.tag == 'self' then - local func = guide.getParentFunction(loc) - ofParentMT(func, callback) - else - callback(loc) - end - local refs = loc.ref - if refs then - for i = 1, #refs do - local ref = refs[i] - if vm.isSet(ref) then - callback(ref) - end - end - end -end - -local function ofGlobal(source, callback) - local key = vm.getKeyName(source) - local node = source.node - if node.tag == '_ENV' then - local uris = files.findGlobals(key) - for _, uri in ipairs(uris) do - local ast = files.getAst(uri) - local globals = vm.getGlobals(ast.ast) - if globals and globals[key] then - for _, src in ipairs(globals[key]) do - if vm.isSet(src) then - callback(src) - end - end - end - end - else - vm.eachField(node, function (src) - if vm.isSet(src) - and key == vm.getKeyName(src) then - callback(src) - end - end) - end -end - -local function ofTableField(source, callback) - callback(source) -end - -local function ofField(source, callback) - local parent = source.parent - local key = vm.getKeyName(source) - local function checkKey(src) - if vm.isSet(src) - and key == vm.getKeyName(src) then - callback(src) - end - end - if parent.type == 'tablefield' - or parent.type == 'tableindex' then - ofTableField(parent, checkKey) - else - local node = parent.node - vm.eachField(node, checkKey) - end -end - -local function ofLiteral(source, 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, callback) - end -end - -local function ofLabel(source, callback) - callback(source) - if source.ref then - for _, ref in ipairs(source.ref) do - if ref.type == 'label' then - callback(ref) - end - end - end -end - -local function ofGoTo(source, callback) - local name = source[1] - local label = guide.getLabel(source, name) - if label then - ofLabel(label, callback) - end -end - -local function findIndex(parent, source) - for i = 1, #parent do - if parent[i] == source then - return i - end - end - return nil -end - -local function findCallRecvs(func, index, callback) - vm.eachRef(func, function (source) - local parent = source.parent - if parent.type ~= 'call' then - return - end - if index == 1 then - local slt = parent.parent - if not slt or slt.type ~= 'select' then - return - end - callback(slt.parent) - else - local slt = parent.extParent and parent.extParent[index-1] - if not slt or slt.type ~= 'select' then - return - end - callback(slt.parent) - end - end) -end - -local function ofFunction(source, callback) - local parent = source.parent - if not parent then - return - end - if parent.type == 'return' then - local func = guide.getParentFunction(parent) - if not func then - return - end - local index = findIndex(parent, source) - if not index then - return - end - findCallRecvs(func, index, function (src) - vm.eachRef(src, callback) - end) - elseif parent.value == source then - vm.eachRef(parent, callback) - end -end - -local function eachDef(source, callback) - local stype = source.type - if stype == 'local' then - ofLocal(source, callback) - elseif stype == 'getlocal' - or stype == 'setlocal' then - ofLocal(source.node, callback) - elseif stype == 'setglobal' - or stype == 'getglobal' then - ofGlobal(source, callback) - elseif stype == 'field' - or stype == 'method' then - ofField(source, callback) - elseif stype == 'setfield' - or stype == 'getfield' then - ofField(source.field, callback) - elseif stype == 'setmethod' - or stype == 'getmethod' then - ofField(source.method, callback) - elseif stype == 'tablefield' then - ofTableField(source, callback) - elseif stype == 'number' - or stype == 'boolean' - or stype == 'string' then - ofLiteral(source, callback) - elseif stype == 'function' then - ofFunction(source, callback) - elseif stype == 'goto' then - ofGoTo(source, callback) - elseif stype == 'label' then - ofLabel(source, callback) - end -end - ---- 获取所有的定义 ---- 只检查语法上的定义,不穿透函数调用 -function vm.eachDef(source, callback, max) - local mark = {} - eachDef(source, function (src) - if mark[src] then - return - end - mark[src] = true - callback(src) - end) -end diff --git a/script-beta/vm/eachField.lua b/script-beta/vm/eachField.lua deleted file mode 100644 index 8c3a26cb..00000000 --- a/script-beta/vm/eachField.lua +++ /dev/null @@ -1,134 +0,0 @@ -local guide = require 'parser.guide' -local files = require 'files' -local vm = require 'vm.vm' - -local function checkNext(source, callback) - local nextSrc = source.next - if not nextSrc then - return - end - local ntype = nextSrc.type - if ntype == 'setfield' - or ntype == 'setmethod' - or ntype == 'getfield' - or ntype == 'getmethod' then - callback(nextSrc) - end - if ntype == 'setindex' - or ntype == 'getindex' then - if nextSrc.node == source then - callback(nextSrc) - end - end - return -end - -local function ofENV(source, callback) - local refs = source.ref - if not refs then - return - end - for i = 1, #refs do - local ref = refs[i] - if ref.type == 'getglobal' - or ref.type == 'setglobal' then - callback(ref) - if guide.getName(ref) == '_G' then - vm.ofField(ref, callback) - local call, index = vm.getArgInfo(ref) - local special = vm.getSpecial(call) - if (special == 'rawset' or special == 'rawget') - and index == 1 then - callback(call.next) - end - end - elseif ref.type == 'getlocal' then - vm.ofField(ref, callback) - end - vm.eachFieldInTable(ref.value, callback) - end -end - -local function ofLocal(source, callback) - if source.tag == '_ENV' then - ofENV(source, callback) - else - vm.eachRef(source, function (src) - vm.ofField(src, callback) - end) - end -end - -local function ofGlobal(source, callback) - vm.eachRef(source, function (src) - vm.ofField(src, callback) - end) -end - -local function ofGetField(source, callback) - vm.eachRef(source, function (src) - vm.ofField(src, callback) - end) -end - -local function ofTable(source, callback) - local parent = source.parent - if parent and parent.value == source then - return vm.eachField(parent, callback) - else - vm.eachFieldInTable(source, callback) - end -end - -local function ofTableField(source, callback) - vm.eachRef(source, function (src) - vm.ofField(src, callback) - end) -end - -function vm.ofField(source, callback) - checkNext(source, callback) - vm.eachMetaValue(source, callback) - vm.eachFieldInTable(source.value, callback) -end - -function vm.eachFieldInTable(value, callback) - if not value then - return - end - if value.type ~= 'table' then - return - end - for i = 1, #value do - local field = value[i] - if field.type == 'tablefield' - or field.type == 'tableindex' then - callback(field) - vm.eachMetaValue(field, callback) - end - end -end - -function vm.eachField(source, callback) - local stype = source.type - if stype == 'local' then - ofLocal(source, callback) - elseif stype == 'getlocal' - or stype == 'setlocal' then - ofLocal(source.node, callback) - elseif stype == 'getglobal' - or stype == 'setglobal' then - ofGlobal(source, callback) - elseif stype == 'table' then - ofTable(source, callback) - elseif stype == 'tablefield' then - ofTableField(source, callback) - elseif stype == 'getfield' - or stype == 'setfield' - or stype == 'getmethod' - or stype == 'setmethod' - or stype == 'getindex' - or stype == 'setindex' then - ofGetField(source, callback) - end -end diff --git a/script-beta/vm/eachRef.lua b/script-beta/vm/eachRef.lua deleted file mode 100644 index 507b713d..00000000 --- a/script-beta/vm/eachRef.lua +++ /dev/null @@ -1,221 +0,0 @@ -local guide = require 'parser.guide' -local files = require 'files' -local vm = require 'vm.vm' - -local function ofParentMT(func, callback) - if not func or func.type ~= 'function' then - return - end - local parent = func.parent - if not parent or parent.type ~= 'setmethod' then - return - end - local node = parent.node - if not node then - return - end - vm.eachRef(node, callback) -end - -local function ofLocal(loc, callback) - -- 方法中的 self 使用了一个虚拟的定义位置 - if loc.tag == 'self' then - local func = guide.getParentFunction(loc) - ofParentMT(func, callback) - else - callback(loc) - end - local refs = loc.ref - if refs then - for i = 1, #refs do - local ref = refs[i] - if ref.type == 'getlocal' then - callback(ref) - elseif ref.type == 'setlocal' then - callback(ref) - end - end - end -end - -local function ofGlobal(source, callback) - local key = vm.getKeyName(source) - local node = source.node - if node.tag == '_ENV' then - local uris = files.findGlobals(key) - for _, uri in ipairs(uris) do - local ast = files.getAst(uri) - local globals = vm.getGlobals(ast.ast) - if globals and globals[key] then - for _, info in ipairs(globals[key]) do - callback(info) - end - end - end - else - vm.eachField(node, function (src) - if key == vm.getKeyName(src) then - callback(src) - end - end) - end -end - -local function ofTableField(source, callback) - local tbl = source.parent - local src = tbl.parent - if not src then - return - end - local key = vm.getKeyName(source) - vm.eachField(src, function (src) - if key == vm.getKeyName(src) then - callback(src) - end - end) -end - -local function ofField(source, callback) - local parent = source.parent - local key = vm.getKeyName(source) - if parent.type == 'tablefield' - or parent.type == 'tableindex' then - ofTableField(parent, callback) - else - local node = parent.node - vm.eachField(node, function (src) - if key == vm.getKeyName(src) then - callback(src) - end - end) - end -end - -local function ofLiteral(source, 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, callback) - end -end - -local function ofLabel(source, callback) - callback(source) - if source.ref then - for _, ref in ipairs(source.ref) do - callback(ref) - end - end -end - -local function ofGoTo(source, callback) - local name = source[1] - local label = guide.getLabel(source, name) - if label then - ofLabel(label, callback) - end -end - -local function findIndex(parent, source) - for i = 1, #parent do - if parent[i] == source then - return i - end - end - return nil -end - -local function findCallRecvs(func, index, callback) - vm.eachRef(func, function (source) - local parent = source.parent - if parent.type ~= 'call' then - return - end - if index == 1 then - local slt = parent.parent - if not slt or slt.type ~= 'select' then - return - end - callback(slt.parent) - else - local slt = parent.extParent and parent.extParent[index-1] - if not slt or slt.type ~= 'select' then - return - end - callback(slt.parent) - end - end) -end - -local function ofFunction(source, callback) - local parent = source.parent - if not parent then - return - end - if parent.type == 'return' then - local func = guide.getParentFunction(parent) - if not func then - return - end - local index = findIndex(parent, source) - if not index then - return - end - findCallRecvs(func, index, function (src) - vm.eachRef(src, callback) - end) - elseif parent.value == source then - vm.eachRef(parent, callback) - end -end - -local function eachRef(source, callback) - local stype = source.type - if stype == 'local' then - ofLocal(source, callback) - elseif stype == 'getlocal' - or stype == 'setlocal' then - ofLocal(source.node, callback) - elseif stype == 'setglobal' - or stype == 'getglobal' then - ofGlobal(source, callback) - elseif stype == 'field' - or stype == 'method' then - ofField(source, callback) - elseif stype == 'setfield' - or stype == 'getfield' then - ofField(source.field, callback) - elseif stype == 'setmethod' - or stype == 'getmethod' then - ofField(source.method, callback) - elseif stype == 'tablefield' then - ofTableField(source, callback) - elseif stype == 'number' - or stype == 'boolean' - or stype == 'string' then - ofLiteral(source, callback) - elseif stype == 'function' then - ofFunction(source, callback) - elseif stype == 'goto' then - ofGoTo(source, callback) - elseif stype == 'label' then - ofLabel(source, callback) - end -end - ---- 获取所有的引用 ---- 可以穿透函数返回值 -function vm.eachRef(source, callback) - local mark = {} - eachRef(source, function (src) - if mark[src] then - return - end - mark[src] = true - callback(src) - end) -end diff --git a/script-beta/vm/init.lua b/script-beta/vm/init.lua index c2fd5265..bf70ea36 100644 --- a/script-beta/vm/init.lua +++ b/script-beta/vm/init.lua @@ -1,7 +1,4 @@ local vm = require 'vm.vm' -require 'vm.eachField' -require 'vm.eachRef' -require 'vm.eachDef' require 'vm.getGlobals' require 'vm.getLinks' require 'vm.getGlobal' diff --git a/test-beta/definition/bug.lua b/test-beta/definition/bug.lua index 823db46d..c9f3f70d 100644 --- a/test-beta/definition/bug.lua +++ b/test-beta/definition/bug.lua @@ -22,13 +22,13 @@ function a:b() end ]] -TEST [[ -function _(...) - function _() - print(<?...?>) - end -end -]] +--TEST [[ +--function _(...) +-- function _() +-- print(<?...?>) +-- end +--end +--]] TEST [[ local <!a!> diff --git a/test-beta/references/init.lua b/test-beta/references/init.lua index bac053c2..6204553a 100644 --- a/test-beta/references/init.lua +++ b/test-beta/references/init.lua @@ -110,35 +110,15 @@ print(t.<!a!>) ]] TEST [[ -local t = { - [<?'a'?>] = 1 -} +t[<?'a'?>] = 1 print(t.<!a!>) ]] ---TEST [[ ---local <!mt!> = {} ---function <!mt!>:a() --- <?self?>:remove() ---end ---]] - TEST [[ -local function f() - return <~function~> () - end -end - -local <!f2!> = f() -]] - -TEST [[ -local function f() - return nil, <~function~> () - end -end - -local _, <!f2!> = f() +local t = { + [<?'a'?>] = 1 +} +print(t.<!a!>) ]] TEST [[ @@ -148,23 +128,21 @@ end ]] TEST [[ -local mt = {} -local <?obj?> = setmetatable({}, mt) -]] +local function f() + return <?function () + end?> +end -TEST [[ -local mt = {} -mt.x = 1 -local obj = setmetatable({}, mt) -print(obj.<?x?>) +local <!f2!> = f() ]] TEST [[ -local x local function f() - return x + return nil, <?function () + end?> end -local <?y?> = f() + +local _, <!f2!> = f() ]] TEST [[ @@ -176,16 +154,6 @@ local y = f() ]] TEST [[ -local x -local function f() - return function () - return x - end -end -local <?y?> = f()() -]] - -TEST [[ local <?x?> local function f() return function () @@ -196,46 +164,16 @@ local y = f()() ]] TEST [[ -local mt = {} -mt.__index = mt - -function mt:add(a, b) -end - -local function init() - return setmetatable({}, mt) -end - -local <!t!> = init() -<?t?>:add() -]] - -TEST [[ -local mt = {} -mt.__index = mt - -function mt:add(a, b) -end - -local function init() - return setmetatable({}, mt) -end - -local t = init() -t:<?add?>() -]] - -TEST [[ local t = {} t.<?x?> = 1 t[a.b.x] = 1 ]] ---TEST [[ ---local t = {} ---t.x = 1 ---t[a.b.<?x?>] = 1 ---]] +TEST [[ +local t = {} +t.x = 1 +t[a.b.<?x?>] = 1 +]] TEST [[ local t @@ -262,6 +200,39 @@ a.b.<?c?> = 1 print(a.b.<!c!>) ]] +TEST [[ +local <!mt!> = {} +function <!mt!>:x() + <?self?>:x() +end +]] + +TEST [[ +local <?mt?> = {} +function <!mt!>:x() + <!self!>:x() +end +]] + +TEST [[ +local mt = {} +function mt:<!x!>() + self:<?x?>() +end +]] + +TEST [[ +local mt = {} +function mt:<?x?>() + self:<!x!>() +end +]] + +TEST [[ +a.<!b!>.c = 1 +print(a.<?b?>.c) +]] + --TEST [[ -----@class <!Class!> -----@type <?Class?> |