当所有扩展都被禁用时,是否会出现这个问题?:是
- 版本:1.84.2(用户设置)
- 提交:1a5daa3
- 日期:2023-11-09T10:51:52.184Z
- Electron:25.9.2
- ElectronBuildId:24603566
- Chromium:114.0.5735.289
- Node.js:18.15.0
- V8:11.4.183.29-electron.0
- OS:Windows_NT x64 10.0.23481
重现步骤:
1.创建一个Lua
文件
- 创建一个包含
function
的字符串 - 在
function
之前和之后不能有字母 - 在字符串后添加一个换行符
5条答案
按热度按时间2cmtqfgy1#
你好,最近我遇到了一个问题,代码片段如下:
这个问题似乎是由于这里的不完美
increaseIndentPattern
导致的:vscode/extensions/lua/language-configuration.json
第25行到第26行的 1c7fa5e
| | "indentationRules": { |
| | "increaseIndentPattern": "^((?!(-\-)).)((\b(else|function|then|do|repeat)\b((?!\b(end|until)\b).))|(\{\s*))$", |
我想说,当前的模式已经解决了9x%的正常使用场景👍,但它有一些主要的缺陷:
end|until
在尾随注解中时,它会导致漏报的情况,例如以下情况:--
(通常意味着一个注解)在字符串字面量中,它也会导致漏报:我一直在尝试改进这个模式,我认为我已经找到了一个更好的解决方案🚀(以及一些测试来证明其正确性)。
我注意到这个问题已经被分配给了 @aiday-mar ,所以我可以直接创建一个PR并链接到这个问题,然后在那里讨论吗?还是我应该在这里发布我的解决方案并先讨论一下再打开一个PR?谢谢😄
a0x5cqrl2#
你好,我最近遇到了这个问题,代码片段如下:
这似乎是由于这里的不完美
increaseIndentPattern
导致的:vscode/extensions/lua/language-configuration.json
第25行到第26行的 1c7fa5e
| | "indentationRules": { |
| | "increaseIndentPattern": "^((?!(\-\-)).)((\b(else|function|then|do|repeat)\b((?!\b(end|until)\b).))|(\{\s*))$", |
我认为当前的模式已经解决了9x%的正常使用场景 👍 但是它有一些主要的缺陷:
我一直在尝试改进这个模式,我认为我已经找到了一个更好的解决方案 🚀 (以及一些测试来证明其正确性)。我注意到这个问题已经被分配给了 @aiday-mar ,所以我可以直接创建一个PR并链接到这个问题,然后在那里讨论吗?还是我应该在这里发布我的解决方案并先讨论一下,然后再打开一个PR?谢谢 😄
在创建PR之前在这里发布你的解决方案有什么原因吗?
rks48beu3#
这是完全没问题的,我在这里提供我的当前解决方案,并在下面解释它。
(我明天会把我的
test.js
附件上传,因为我现在手头上没有)解释
如上所述,现有模式存在
3
主要缺陷,我的解决方案旨在解决所有这些问题1. 字符串字面量中的关键字
为了正确忽略字符串字面量的关键字,我们的想法是在匹配关键字之前的序列之前消耗引用的字符串。我从这个帖子中借来了这个想法: https://stackoverflow.com/a/23667311
"string literal"
而不是只使用点来匹配前缀序列中的任何字符,我们将其拆分为两部分:
.
non quote character
,我们只需匹配它:[^"]
否则我们应该消耗整个引用的字符串,即匹配直到关闭引号:
"[^"]*"
这给出了类似于以下内容的东西:
([^"]|"[^"]*")*
[^"]*
部分需要分成另外两个情况:\\"
(?!\\")[^"]
[^"]*
变成(\\"|[^"])*
=> 因此这部分最终变成
([^"]|"(\\"|(?!\\")[^"])*")*
'string literal
它们是一样的,只需将双引号替换为单引号:
([^']|'(\\'|(?!\\')[^'])*')*
在与上面的双引号情况合并后:
([^"']|"(\\"|(?!\\")[^"])*"|'(\\'|(?!\\')[^'])*')*
(?!\-\-)
=>
((?!\-\-)[^"']|"(\\"|(?!\\")[^"])*"|'(\\'|(?!\\')[^'])*')*
这是解决方案的第一部分。
2. 尾随注解中的关键字
上述技巧保证匹配的关键字不是字符串的一部分。现在我们需要处理一种情况,即如果有
end|until
关键字,下一行不应该缩进。仅仅检查end|until
是不够的,因为它们可能位于字符串或尾随注解中间。=>
\\s*(\\-\\-.*)?
else|then|do|repeat
这个关键字要复杂得多,因为一个函数可以被命名为或者匿名的,而且它可能是一个(未完成的)参数列表。我的观察是,在有效的语法中,如果我们期望有一个缩进,那么函数声明最多应该以右括号结尾。右括号是可选的,但是一旦我们匹配到了它,就没有什么(除了尾随空格和注解当然)是可以允许的。所以无论我们检查不带
)
是否都行。只要允许尾随空格或注解就可以决定下一行是否缩进。[^)]+\)?
关键字可选地跟随任何内容,并且如果存在任何内容,我们应该在 xm37n1x 时停止。=> xm44n1x
这就是解决方案的第二部分。
3. 在字符串中的 xm45n1x 将导致误报负数
这个问题由第一部分的解决方案解决,因为现在字符串被正确忽略了。而且任何匹配为 xm46n1x 的实际上现在是注解前缀了。
bonus:允许在 xm47n1x 之后有尾随注解
在原始模式中,它只是允许在 xm48n1x 之后有尾随空格。
=> xm52n1x
=> xm53n1x
All together 🎉
xam54b0xa
如前所述,我明天会发布我的
test.js
。同时,您可以通过 regex101 进行测试,或者在本地编辑
extensions/lua/language-configuration.json
文件以直接在 vscode 中进行测试。z4bn682m4#
我刚刚找到了一个更高效的检查引用字符串的方法👀
"[^"\\]*(?:\\.[^"\\]*)*"
参考: https://stackoverflow.com/a/6525975
我在regex101的调试器中比较了它的性能,它比我提出的
"(\\"|(?!\\")[^"])*"
快得多(使用更少的步骤)local s = "this is a test string"
16
步local s = "this is a test string
37
步报告失败匹配我一定会把它纳入我提出的解决方案中😄
bgtovc5b5#
测试文件
这是我的
test.js
,它包含了我在解决方案开发过程中使用正则表达式的各个阶段。你可以将const PATTERN =
更改为指向不同的阶段,以查看测试结果是如何演变的。最新解决方案
与我之前的版本相比,最新解决方案略有不同。我使用了 正向后视 来检查 函数参数 ,并将其放在关键字分支之后:
((?<=function)[^)]+\)?)?
。我认为这会使它更具可读性和可编辑性,因为所有的关键字都分组在一起。 🤔带注解的版本
我还制作了一个带注解的版本(使用命名组)以增加详细程度:
再次分解
^(?<not_cmt>(?!\-\-)[^"']|(?<dq_str>"[^"\\]*(\\.[^"\\]*)*")|(?<sq_str>'[^'\\]*(\\.[^'\\]*)*'))*
:匹配直到遇到注解,遇到引号时消耗整个引号字符串(?!\-\-)[^"']
:任何不是注解和不是引号的字符,组内互斥(?<dq_str>"[^"\\]*(\\.[^"\\]*)*")
:匹配双引号字符串(?<sq_str>'[^'\\]*(\\.[^'\\]*)*')
:匹配单引号字符串(\b(?<kw>else|function|then|do|repeat)\b(?<fparam>(?<=function)[^)]+\)?)?|(?<bracket>[\{\(]))
:匹配关键字或括号\b(?<kw>else|function|then|do|repeat)\b
:匹配边界上的关键字(?<fparam>(?<=function)[^)]+\)?)?
:匹配特定于function
关键字的可选参数列表(?<bracket>[\{\(])
:匹配括号(?<trail>\s*(\-\-.*)?)$
:如果关键字或括号之后有任何内容,必须是尾随空格或注解