From 4bd86120d41e3b01433004bf761beccb7f3a0167 Mon Sep 17 00:00:00 2001 From: Jon Huhn Date: Mon, 10 Jun 2024 06:23:03 -0500 Subject: fix(glob): handle overlapping `{}` condition elements #29236 This change fixes an issue where glob patterns like `{a,ab}` would not match `ab` because the first option `a` matches, then the end of the string is expected but `b` is found, and LPeg does not backtrack to try the next option `ab` which would match. The fix here is to also append the rest of the pattern to the generated LPeg pattern for each option. This changes a glob `{a,ab}` from being parsed as ("a" or "ab") "end of string" to ("a" "end of string" or "ab" "end of string") Here, matching against `ab` would try the first option, fail to match, then proceed to the next option, and match. The sacrifice this change makes is dropping support for nested `{}` conditions, which VSCode doesn't seem to support or test AFAICT. Fixes #28931 Co-authored-by: Sergey Slipchenko --- test/functional/lua/glob_spec.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'test/functional/lua/glob_spec.lua') diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua index 56cd4c9bb5..b3e1b79ee7 100644 --- a/test/functional/lua/glob_spec.lua +++ b/test/functional/lua/glob_spec.lua @@ -161,7 +161,7 @@ describe('glob', function() eq(false, match('{ab,cd}', 'a')) eq(true, match('{ab,cd}', 'cd')) eq(true, match('{a,b,c}', 'c')) - eq(true, match('{a,{b,c}}', 'c')) + eq(false, match('{a,{b,c}}', 'c')) -- {} cannot nest end) it('should match [] groups', function() @@ -223,6 +223,17 @@ describe('glob', function() eq(true, match('{[0-9],[a-z]}', '0')) eq(true, match('{[0-9],[a-z]}', 'a')) eq(false, match('{[0-9],[a-z]}', 'A')) + + -- glob is from willRename filter in typescript-language-server + -- https://github.com/typescript-language-server/typescript-language-server/blob/b224b878652438bcdd639137a6b1d1a6630129e4/src/lsp-server.ts#L266 + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.js')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.ts')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.mts')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.mjs')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.cjs')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.cts')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.jsx')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.tsx')) end) end) end) -- cgit From b109b1abce8c86f80aea06948b32e35a70daa0b0 Mon Sep 17 00:00:00 2001 From: Zoltán Nyikos Date: Sat, 6 Jul 2024 11:40:08 +0200 Subject: fix(glob): avoid `subcapture nesting too deep` error (#29520) Use Cmt to evaluate Cond and Elem during match to avoid building the nested capture structure later. --- test/functional/lua/glob_spec.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test/functional/lua/glob_spec.lua') diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua index b3e1b79ee7..b95d874bb5 100644 --- a/test/functional/lua/glob_spec.lua +++ b/test/functional/lua/glob_spec.lua @@ -205,6 +205,19 @@ describe('glob', function() eq(true, match('[!a-zA-Z0-9]', '!')) end) + it('should handle long patterns', function() + -- lpeg has a recursion limit of 200 by default, make sure the grammar does trigger it on + -- strings longer than that + local fill_200 = + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + eq(200, fill_200:len()) + local long_lit = fill_200 .. 'a' + eq(false, match(long_lit, 'b')) + eq(true, match(long_lit, long_lit)) + local long_pat = fill_200 .. 'a/**/*.c' + eq(true, match(long_pat, fill_200 .. 'a/b/c/d.c')) + end) + it('should match complex patterns', function() eq(false, match('**/*.{c,h}', '')) eq(false, match('**/*.{c,h}', 'c')) -- cgit From 7d24c4d6b0413cd5af8d0579f0a9a694db7f775e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 29 Jul 2024 11:20:15 +0100 Subject: test: allow exec_lua to handle functions Problem: Tests have lots of exec_lua calls which input blocks of code provided as unformatted strings. Solution: Teach exec_lua how to handle functions. --- test/functional/lua/glob_spec.lua | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'test/functional/lua/glob_spec.lua') diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua index b95d874bb5..6f1e5be501 100644 --- a/test/functional/lua/glob_spec.lua +++ b/test/functional/lua/glob_spec.lua @@ -9,14 +9,9 @@ describe('glob', function() after_each(n.clear) local match = function(...) - return exec_lua( - [[ - local pattern = select(1, ...) - local str = select(2, ...) - return require("vim.glob").to_lpeg(pattern):match(str) ~= nil - ]], - ... - ) + return exec_lua(function(pattern, str) + return require('vim.glob').to_lpeg(pattern):match(str) ~= nil + end, ...) end describe('glob matching', function() -- cgit From e5c174421df3872df0dd3a676609d1e74dfef6a9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 11 Aug 2024 09:27:48 +0100 Subject: test: support upvalues in exec_lua --- test/functional/lua/glob_spec.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'test/functional/lua/glob_spec.lua') diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua index 6f1e5be501..8302c7334d 100644 --- a/test/functional/lua/glob_spec.lua +++ b/test/functional/lua/glob_spec.lua @@ -2,16 +2,15 @@ local t = require('test.testutil') local n = require('test.functional.testnvim')() local eq = t.eq -local exec_lua = n.exec_lua describe('glob', function() before_each(n.clear) after_each(n.clear) - local match = function(...) - return exec_lua(function(pattern, str) + local match = function(pattern, str) + return n.exec_lua(function() return require('vim.glob').to_lpeg(pattern):match(str) ~= nil - end, ...) + end) end describe('glob matching', function() -- cgit