diff options
author | uhziel <uhziel@gmail.com> | 2020-12-11 16:12:56 +0800 |
---|---|---|
committer | uhziel <uhziel@gmail.com> | 2020-12-11 16:12:56 +0800 |
commit | 93cdf898f5eb8282dba0d684f926e26c6a9f7dbd (patch) | |
tree | 1479b7923cf7afdba0b792bda824165d1bfa3fd2 | |
parent | 64e62cfefbeff094b2d168ed5d0d31d48736c89b (diff) | |
download | lua-language-server-93cdf898f5eb8282dba0d684f926e26c6a9f7dbd.zip |
通过不向前推断、在vm缓存doc.class查询fields来加快分析速度
-rw-r--r-- | script/core/diagnostics/undefined-field.lua | 40 | ||||
-rw-r--r-- | script/parser/guide.lua | 4 | ||||
-rw-r--r-- | script/vm/eachField.lua | 5 | ||||
-rw-r--r-- | test/diagnostics/init.lua | 57 |
4 files changed, 85 insertions, 21 deletions
diff --git a/script/core/diagnostics/undefined-field.lua b/script/core/diagnostics/undefined-field.lua index 307182b3..ab707f7c 100644 --- a/script/core/diagnostics/undefined-field.lua +++ b/script/core/diagnostics/undefined-field.lua @@ -11,39 +11,37 @@ return function (uri, callback) return end - local function is_G(src) - if not src then - return false - end - while src.node ~= nil and src.type == 'getfield' and src.field[1] == '_G' do - src = src.node + local function getDocClassFromInfer(src) + local infers = vm.getInfers(src, 0) + + if not infers then + return nil end - return src.type == 'getglobal' and src.special == '_G' - end - local function canInfer2Class(src) - local className = vm.getClass(src, 0) - if not className then - local inferType = vm.getInferType(src, 0) - if inferType ~= 'any' and inferType ~= 'table' then - className = inferType + for i = 1, #infers do + local infer = infers[i] + if infer.type ~= '_G' then + local inferSource = infer.source + if inferSource.type == 'doc.class' then + return inferSource + elseif inferSource.type == 'doc.class.name' then + return inferSource.parent + end end end - return className and className ~= 'table' + return nil end local function checkUndefinedField(src) local fieldName = guide.getKeyName(src) - if is_G(src)then - return - end - if not canInfer2Class(src.node) then + local docClass = getDocClassFromInfer(src.node) + if not docClass then return end - - local refs = vm.getFields(src.node, 0) + + local refs = vm.getFields(docClass) local fields = {} local empty = true diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 022be26d..fcf96aa2 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -1242,6 +1242,10 @@ function m.isDoc(source) return source.type:sub(1, 4) == 'doc.' end +function m.isDocClass(source) + return source.type == 'doc.class' +end + --- 根据函数的调用参数,获取:调用,参数索引 function m.getCallAndArgIndex(callarg) local callargs = callarg.parent diff --git a/script/vm/eachField.lua b/script/vm/eachField.lua index fabb11c7..19ac77e9 100644 --- a/script/vm/eachField.lua +++ b/script/vm/eachField.lua @@ -45,6 +45,11 @@ function vm.getFields(source, deep) or getFieldsBySource(source, deep) vm.getCache('eachFieldOfGlobal')[name] = cache return cache + elseif guide.isDocClass(source) then + local cache = vm.getCache('eachFieldOfDocClass')[source] + or getFieldsBySource(source, deep) + vm.getCache('eachFieldOfDocClass')[source] = cache + return cache else return getFieldsBySource(source, deep) end diff --git a/test/diagnostics/init.lua b/test/diagnostics/init.lua index 27a7e5f5..b923b8b6 100644 --- a/test/diagnostics/init.lua +++ b/test/diagnostics/init.lua @@ -824,6 +824,7 @@ TEST [[ local t ]] +-- checkUndefinedField 通用 TEST [[ ---@class Foo ---@field field1 integer @@ -865,3 +866,59 @@ local mt3 function mt3:method() return 1 end print(mt3:method()) ]] + +-- checkUndefinedField 通过type找到class +TEST [[ +---@class Foo +local Foo +function Foo:method1() end + +---@type Foo +local v +v:method1() +<!v:method2!>() -- doc.class.name +]] + +-- checkUndefinedField 通过type找到class,涉及到 class 继承版 +TEST [[ +---@class Foo +local Foo +function Foo:method1() end +---@class Bar: Foo +local Bar +function Bar:method3() end + +---@type Bar +local v +v:method1() +<!v:method2!>() -- doc.class.name +v:method3() +]] + +-- checkUndefinedField 类名和类变量同名,类变量被直接使用 +TEST [[ +---@class Foo +local Foo +function Foo:method1() end +<!Foo:method2!>() -- doc.class +<!Foo:method2!>() -- doc.class +]] + +-- checkUndefinedField 没有@class的不检测 +TEST [[ +local Foo +function Foo:method1() + return Foo:method2() -- table +end +]] + +-- checkUndefinedField 类名和类变量不同名,类变量被直接使用、使用self +TEST [[ +---@class Foo +local mt +function mt:method1() + <!mt.method2!>() -- doc.class + self.method1() + return <!self.method2!>() -- doc.class.name +end +]] |