Skip to content

Conversation

@uhziel
Copy link
Contributor

@uhziel uhziel commented Dec 10, 2020

在实际项目中,希望能尽量检查到拼写错误这种情况。Lua 不像静态语言那样能通过编译发现这种错误,而出现这种拼写错误带来的结果一般都不好。

lua-language-server 对下面前 3 种拼写错误的检查良好,但对第4种目前看并没有提供支持:

  1. 参数名错误
  2. local 变量错误
  3. 全局变量错误
  4. 成员变量错误

尝试实现下第4种。麻烦看下我这思路是否可行,一边看代码一边在写,有理解不对的地方请指出。

目前的实现,只有被认为是类的field,才会进行这种检查。因为在实际试用中,发现不这么做会检查出非常多的干扰项。

剩余可能还需要处理的:

  1. 类似 undefined global 添加对废弃接口的警告
  2. 处理一些遇到的特殊情况
@uhziel uhziel changed the title Diagnostic undefined field 添加检查"未定义的 field"Diagnostic undefined field Dec 10, 2020
@sumneko
Copy link
Collaborator

sumneko commented Dec 10, 2020

检查未定义的字段主要有2个问题:

  1. 准确度很差
  2. 可能会有性能问题

如果只检查类的字段存在性,准确度应该基本可以接受,但还是需要在实际的项目中测试。
比较担心的是性能问题,由于Lua的动态性,查询一个对象的定义的开销还是挺高的。在诊断中势必要对所有的 field.node 求定义,这个整体开销在实际的项目中可能会无法接受。
此外,警告等级定义为 Warning 的诊断会在后台对工作区的所有文件进行,这个可能也需要一些处理。

@uhziel
Copy link
Contributor Author

uhziel commented Dec 10, 2020

  1. 我这边有个二千多lua文件的公司内部项目,现在正在针对它进行测试,应该可以提供个比较有意义的校验。

  2. 对于性能问题,我在测试时候,倒是没太感受到性能问题。
    这个在后台的诊断,我在哪里可以看到后台堆积情况和处理速度了?

  3. 你是说建议默认配置为 Hint 级别,让其只对打开的文件进行分析。是吧?

@sumneko
Copy link
Collaborator

sumneko commented Dec 10, 2020

后台速度可以对比全文诊断耗时估算出来,这个在日志里会有反应。
从语义上讲,这个诊断应该确实是 Warning 级别的,只是我目前只设置了Hint级别不诊断(刚好之前有几个性能消耗大户,比如检查函数调用时的多余参数刚好应该是 Hint 级别)。如果要假如这个诊断,可能需要加入新的设置,比如指定某些诊断不在后台进行。

@uhziel
Copy link
Contributor Author

uhziel commented Dec 10, 2020

image
btw,我在开启这个诊断后,在 script\brave\work.lua 里 brave.on('compile', function (text) 发现的 infer 问题,state 的类型是nil了。

@uhziel
Copy link
Contributor Author

uhziel commented Dec 10, 2020

看了下,确实如你所说,挺慢的,之前是在后台没感知到。我看到有单个.lua分析 undefined-field 最多花费5分钟的。

我这里有个思路,你看下是否具有可行性了?

核心思想是在做这种检查时,忽视其动态性
比如,对于 meta\template\math.lua 里的 @class math 来说,我只认其 doc.class 下绑定的 field 和 bindSource里的方法。
对于这种会标记@Class 的类,很少会有人动态在外部给其添加 field 吧。如果真这么做,也只要添加相应 @field 即可。

具体实现来说,只在 local infers = vm.getInfers(source, deep) 后再用 infers 往前查一层即可。不用使用耗时的vm.getFields(src.node, 0)

这里倒是绕不开vm.getInfers(source, deep) ,这个接口的实现看着不会各种穿透,消耗上应该会好不少吧?

@sumneko
Copy link
Collaborator

sumneko commented Dec 10, 2020

deep 不传值可以不进行动态推断以及不向前推断(大概?)。
判断是否有字段还是应该用 getFields ,只是你这里只对 class 做检查的话,可以缓存某个 class 中的字段。这个缓存也许可以考虑由 vm 层实现。

@sumneko
Copy link
Collaborator

sumneko commented Dec 10, 2020

此外我目前在 getFields 中没有区分定义和引用,也许可以单独做个只查找定义的 getFields ,这个配合不向前查找,应该能大幅加快速度。

@sumneko sumneko merged commit 6172b5d into LuaLS:master Dec 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants