Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在拥有类继承关系的变量值上,自动补全可能不全 #318

Closed
uhziel opened this issue Dec 21, 2020 · 12 comments
Closed

在拥有类继承关系的变量值上,自动补全可能不全 #318

uhziel opened this issue Dec 21, 2020 · 12 comments

Comments

@uhziel
Copy link
Contributor

uhziel commented Dec 21, 2020

Describe the bug
image
上面应该也提示 Foo 的 bar1、bar2 才对,结果只有 Foo2 的 bar3。

To Reproduce

---@class Foo
Foo = {}
function Foo:Constructor()
    self.bar1 = 1
    self.bar2 = 1
end

---@class Foo2: Foo
Foo2 = {}
function Foo2:Constructor()
    self.bar3 = 1
end

---@type Foo2
local v
print(v.)

拷贝上面内容到新lua文件,对“print(v.)”里的.删除再重输,可复现。

Expected behavior
应该 bar1、bar2、bar3 均出现。
btw,如果 Foo、Foo2 为 local 变量,而不是全局变量,不会有上述问题。

Screenshots
上面已附加

Environment (please complete the following information):

  • OS: Windows
  • Is WSL remote? no
  • Client: VSCode

Additional context
Add any other context about the problem here.

@uhziel
Copy link
Contributor Author

uhziel commented Dec 22, 2020

看着根本原因是 getRefCache() 获取错误 cache 导致的。

function m.searchRefs(status, obj, mode)
    local cache, makeCache = m.getRefCache(status, obj, mode)
...
    m.searchSameFields(status, simple, mode) -- 这里又嵌套调用 m.searchRefs() 获取同全局变量的 cache,最后获取是一个空的{} cache
...
    makeCache(status.results)

== 细节版 ==

下面用例放到 test\diagnostics\init.lua

TEST [[
---@class Foo
Foo = {}
function Foo:Constructor()
    self.bar1 = 1
end

---@class Foo2: Foo
local Foo2 = {}
function Foo2:Constructor()
    self.bar2 = 1
end

---@type Foo2
local v
print(v.bar1)  
]]
添加断点红框代码测试代码,第二次命中时会出现复现版堆栈。
有什么好的修改意见没?

image

@sumneko
Copy link
Collaborator

sumneko commented Dec 22, 2020

晚点研究一下

@uhziel
Copy link
Contributor Author

uhziel commented Dec 22, 2020

之前我也尝试修改过。对于单点的我示例里的问题,因为获取 cache 失败导致的 searchSameFieldsCrossMethod() 穿透失败,感觉可能通过在 cache 上新增未完成标志做出特殊处理。但这个获取cache可能失效的情况,看着也会影响其他逻辑,最好能从根本上处理,但可能还缺乏对你之前思考的理解,没想到什么好的方法。

@sumneko
Copy link
Collaborator

sumneko commented Dec 23, 2020

原因是穿越method的标记,从外往里穿的时候是共享了一个全局标记,导致穿过一次以后就穿不了了。我改成了每个method用单独的标记了。
至于你说的 getRefCache 我没仔细看,但应该关系不大,那里的处理是为了防止死循环的,无论如何都不应该在访问一个全局变量的过程中再去访问相同的全局变量。

@uhziel
Copy link
Contributor Author

uhziel commented Dec 24, 2020

嗯嗯了解~
不过个人从调试中感觉,隐藏更深的原因是,getRefCache()在还未生成完成时被嵌套使用了。
我在调试中发现 Foo 就算改是 local 变量,也会有这种searchRefs() 嵌套调用自身的情况 。
下面是 searchRefs(Foo getlocal ) 里又会调用 searchRefs(同一 Foo getlocal) 的情况,一旦还有什么公用的数据被使用,可能还会类似我报的这种bug。
image
单从这个堆栈上看,最上面的那个 searchRefs() 要能被去掉就好了,可以避免bug加提高查找速度。

如果有理解不对的地方,请指出

@sumneko
Copy link
Collaborator

sumneko commented Dec 24, 2020

同一个对象就是不应该在 searchRefs 的过程中再次 searchRefs 的,否则不就死循环了吗。
如: A = B;B = A

@uhziel
Copy link
Contributor Author

uhziel commented Dec 24, 2020

同意。我想表达的意思是,能不能把最上面的 searchRefs() 调用去除。因为多的这一次调用,可能导致其他逻辑被影响。
我这里反馈的自动补全不全问题,是冗余的 searchRefs() 调用里 searchSameMethod() 改了 mark['method'],改变了公用数据 。可能其他地方,或者后续的开发,也会被这个冗余的 searchRefs() 调用影响。

@sumneko
Copy link
Collaborator

sumneko commented Dec 24, 2020

如果去掉后测试可以通过就行

@uhziel
Copy link
Contributor Author

uhziel commented Dec 24, 2020

目前想着不成熟的可能做法是这样:
(仅仅基于对 searchRefs() 的思考,但实际上 searchFields() 等的被影响也得考虑下)

  • 在 status 上记录调用层级,比如上一层是 CrossMethod,上一层 searchRef
  • 通过这个调用层级,来识别当前是不是应该继续 CrossMethod 或则是其他
  • 当然这个可能对本就复杂的穿透逻辑带来更多的复杂度,可行性还需要进一步考虑

对我而言,可能还要继续熟悉你的代码,才能做类似的开发了。btw,我在调试时,有时会发现 queue 里同一条目多次出现,要是能把它优化掉去除冗余,可能对查找速度也会有些帮助了。

@sumneko
Copy link
Collaborator

sumneko commented Dec 24, 2020

过滤的话,直接在share里做标记就行了
queue里的同一个条目多次出现是有过滤的,对速度应该影响不大

@sumneko
Copy link
Collaborator

sumneko commented Dec 24, 2020

目前对性能影响比较大的应该是后退查找太多了,这个我之后会想办法优化一下,哪怕牺牲一些准确度。
后退查找指:

local v = t
v.<!x!> = 1
print(t.<?x?>)

@uhziel
Copy link
Contributor Author

uhziel commented Dec 24, 2020

嗯嗯确实queue有同条目过滤。
后退查找这个还不大懂,还得更熟悉下才行了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants