Skip to content

Commit 742d7d7

Browse files
authored
[glob] Remove top-level braces, if any (#2373)
* [glob] Remove top-level braces, if any This works around long braced glob expressions that some servers send. * [lsp-rf]: don't keep track of number for match group
1 parent 597febf commit 742d7d7

File tree

3 files changed

+76
-47
lines changed

3 files changed

+76
-47
lines changed

clients/lsp-rf.el

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@
8484
(mapcar 'expand-file-name lsp-rf-language-server-start-command))
8585

8686
(defun parse-rf-language-server-globs-to-regex (vector)
87-
"Converts `vector' with globs to regex."
88-
(concat "\\(" (mapconcat #'lsp-glob-to-regexp vector "\\|") "\\)"))
87+
"Convert a VECTOR of globs to a regex."
88+
(--> (mapcan #'lsp-glob-to-regexps vector)
89+
(s-join "\\|" it)
90+
(concat "\\(?:" it "\\)")))
8991

9092
(defun parse-rf-language-server-include-path-regex (vector)
9193
"Creates regexp to select files from workspace directory."

lsp-mode.el

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,9 +2545,27 @@ an Elisp regexp."
25452545
glob-segments)
25462546
current-regexp)))))
25472547

2548-
(defun lsp-glob-to-regexp (pattern)
2549-
"Convert a PATTERN from LSP's glob syntax to an Elisp regexp."
2550-
(concat "\\`" (lsp--glob-to-regexp (string-trim pattern)) "\\'"))
2548+
;; See https://github.com/emacs-lsp/lsp-mode/issues/2365
2549+
(defun lsp-glob-unbrace-at-top-level (glob-pattern)
2550+
"If GLOB-PATTERN does not start with a brace, return a singleton list containing GLOB-PATTERN.
2551+
2552+
If GLOB-PATTERN does start with a brace, return a list of the
2553+
comma-separated globs within the top-level braces."
2554+
(if (not (string-prefix-p "{" glob-pattern))
2555+
(list glob-pattern)
2556+
(lsp-split-glob-pattern (substring glob-pattern 1 -1) ?\,)))
2557+
2558+
(defun lsp-glob-convert-to-wrapped-regexp (glob-pattern)
2559+
"Convert GLOB-PATTERN to a regexp wrapped with the beginning-
2560+
and end-of-string meta-characters."
2561+
(concat "\\`" (lsp--glob-to-regexp (string-trim glob-pattern)) "\\'"))
2562+
2563+
(defun lsp-glob-to-regexps (glob-pattern)
2564+
"Convert a GLOB-PATTERN to a list of Elisp regexps."
2565+
(let* ((trimmed-pattern (string-trim glob-pattern))
2566+
(top-level-unbraced-patterns (lsp-glob-unbrace-at-top-level trimmed-pattern)))
2567+
(seq-map #'lsp-glob-convert-to-wrapped-regexp
2568+
top-level-unbraced-patterns)))
25512569

25522570

25532571

@@ -3314,6 +3332,7 @@ disappearing, unset all the variables related to it."
33143332
(defun lsp--file-process-event (session root-folder event)
33153333
"Process file event."
33163334
(let* ((changed-file (cl-third event))
3335+
(rel-changed-file (f-relative changed-file root-folder))
33173336
(event-numeric-kind (alist-get (cl-second event) lsp--file-change-type))
33183337
(bit-position (1- event-numeric-kind))
33193338
(watch-bit (ash 1 bit-position)))
@@ -3338,9 +3357,11 @@ disappearing, unset all the variables related to it."
33383357
(-lambda ((&FileSystemWatcher :glob-pattern :kind?))
33393358
(when (or (null kind?)
33403359
(> (logand kind? watch-bit) 0))
3341-
(-let [glob-regex (lsp-glob-to-regexp glob-pattern)]
3342-
(or (string-match glob-regex changed-file)
3343-
(string-match glob-regex (f-relative changed-file root-folder))))))))))))
3360+
(-let [regexes (lsp-glob-to-regexps glob-pattern)]
3361+
(-any? (lambda (re)
3362+
(or (string-match re changed-file)
3363+
(string-match re rel-changed-file)))
3364+
regexes))))))))))
33443365
(with-lsp-workspace workspace
33453366
(lsp-notify
33463367
"workspace/didChangeWatchedFiles"

test/lsp-file-watch-test.el

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -142,59 +142,65 @@
142142
(should (equal expected-events events))
143143
(lsp-kill-watch watch)))
144144

145+
(ert-deftest lsp-file-watch--glob-split ()
146+
(should (equal (lsp-glob-unbrace-at-top-level "{/home/alice/project/**/*.hs,/home/alice/project/stack.yaml}")
147+
'("/home/alice/project/**/*.hs" "/home/alice/project/stack.yaml")))
148+
(should (equal (lsp-glob-unbrace-at-top-level "{/home/alice/project/**/*.{ml,eliom},/home/alice/project/dune.project}")
149+
'("/home/alice/project/**/*.{ml,eliom}" "/home/alice/project/dune.project"))))
150+
145151
(ert-deftest lsp-file-watch--glob-pattern ()
146-
(should (string-match (lsp-glob-to-regexp "pom.xml") "pom.xml"))
147-
(should (string-match (lsp-glob-to-regexp "**/pom.xml") "/pom.xml"))
148-
(should (string-match (lsp-glob-to-regexp "**/*.xml") "data/pom.xml"))
149-
(should (string-match (lsp-glob-to-regexp "**/*.xml") "pom.xml"))
152+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "pom.xml") "pom.xml"))
153+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/pom.xml") "/pom.xml"))
154+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/*.xml") "data/pom.xml"))
155+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/*.xml") "pom.xml"))
150156

151157
;; Some VSCode tests
152158
;; (https://github.com/Microsoft/vscode/blob/466da1c9013c624140f6d1473b23a870abc82d44/src/vs/base/test/node/glob.test.ts)
153-
(should (string-match (lsp-glob-to-regexp "**/.*") ".git"))
154-
(should (string-match (lsp-glob-to-regexp "**/.*") ".hidden.txt"))
155-
(should (not (string-match (lsp-glob-to-regexp "**/.*") "git")))
156-
(should (not (string-match (lsp-glob-to-regexp "**/.*") "hidden.txt")))
159+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") ".git"))
160+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") ".hidden.txt"))
161+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") "git")))
162+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") "hidden.txt")))
157163

158-
(should (string-match (lsp-glob-to-regexp "**/.*") "path/.git"))
159-
(should (string-match (lsp-glob-to-regexp "**/.*") "path/.hidden.txt"))
160-
(should (not (string-match (lsp-glob-to-regexp "**/.*") "path/git")))
161-
(should (not (string-match (lsp-glob-to-regexp "**/.*") "pat.h/hidden.txt")))
164+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") "path/.git"))
165+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") "path/.hidden.txt"))
166+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") "path/git")))
167+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "**/.*") "pat.h/hidden.txt")))
162168

163-
(should (string-match (lsp-glob-to-regexp "**/node_modules/**") "node_modules"))
164-
(should (string-match (lsp-glob-to-regexp "**/node_modules/**") "node_modules/"))
165-
(should (not (string-match (lsp-glob-to-regexp "**/node_modules/**") "node/_modules/")))
169+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/node_modules/**") "node_modules"))
170+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "**/node_modules/**") "node_modules/"))
171+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "**/node_modules/**") "node/_modules/")))
166172

167-
(should (string-match (lsp-glob-to-regexp "?") "h"))
168-
(should (not (string-match (lsp-glob-to-regexp "?") "hi")))
173+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "?") "h"))
174+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "?") "hi")))
169175

170-
(should (string-match (lsp-glob-to-regexp "foo.[[]") "foo.["))
176+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[[]") "foo.["))
171177

172-
(should (string-match (lsp-glob-to-regexp "{foo,bar}/**") "foo"))
173-
(should (string-match (lsp-glob-to-regexp "{foo,bar}/**") "bar"))
174-
(should (string-match (lsp-glob-to-regexp "{foo,bar}/**") "foo/test"))
175-
(should (string-match (lsp-glob-to-regexp "{foo,bar}/**") "bar/test"))
178+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{foo,bar}/**") "foo"))
179+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{foo,bar}/**") "bar"))
180+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{foo,bar}/**") "foo/test"))
181+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{foo,bar}/**") "bar/test"))
176182

177-
(should (string-match (lsp-glob-to-regexp "{**/*.d.ts,**/*.js}") "/testing/foo.js"))
178-
(should (string-match (lsp-glob-to-regexp "{**/*.d.ts,**/*.js}") "testing/foo.d.ts"))
179-
(should (string-match (lsp-glob-to-regexp "{**/*.d.ts,**/*.js,foo.[0-9]}") "foo.5"))
183+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{**/*.d.ts,**/*.js}") "/testing/foo.js"))
184+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{**/*.d.ts,**/*.js}") "testing/foo.d.ts"))
185+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "{**/*.d.ts,**/*.js,foo.[0-9]}") "foo.5"))
180186

181-
(should (string-match (lsp-glob-to-regexp "some/**/*") "some/foo.js"))
182-
(should (string-match (lsp-glob-to-regexp "some/**/*") "some/folder/foo.js"))
187+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "some/**/*") "some/foo.js"))
188+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "some/**/*") "some/folder/foo.js"))
183189

184-
(should (not (string-match (lsp-glob-to-regexp "some/**/*") "something/foo.js")))
185-
(should (not (string-match (lsp-glob-to-regexp "some/**/*") "something/folder/foo.js")))
190+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "some/**/*") "something/foo.js")))
191+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "some/**/*") "something/folder/foo.js")))
186192

187-
(should (not (string-match (lsp-glob-to-regexp "{**/*.d.ts,**/*.js,foo.[0-9]}") "foo.f")))
188-
(should (string-match (lsp-glob-to-regexp "prefix/{**/*.d.ts,**/*.js,foo.[0-9]}") "prefix/foo.8"))
189-
(should (not (string-match (lsp-glob-to-regexp "prefix/{**/*.d.ts,**/*.js,foo.[0-9]}") "prefix/foo.f")))
193+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "{**/*.d.ts,**/*.js,foo.[0-9]}") "foo.f")))
194+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "prefix/{**/*.d.ts,**/*.js,foo.[0-9]}") "prefix/foo.8"))
195+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "prefix/{**/*.d.ts,**/*.js,foo.[0-9]}") "prefix/foo.f")))
190196

191-
(should (not (string-match (lsp-glob-to-regexp "foo.[!0-9]") "foo.5")))
192-
(should (not (string-match (lsp-glob-to-regexp "foo.[!0-9]") "foo.8")))
193-
(should (string-match (lsp-glob-to-regexp "foo.[!0-9]") "foo.f"))
197+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[!0-9]") "foo.5")))
198+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[!0-9]") "foo.8")))
199+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[!0-9]") "foo.f"))
194200

195-
(should (not (string-match (lsp-glob-to-regexp "foo.[^0-9]") "foo.5")))
196-
(should (not (string-match (lsp-glob-to-regexp "foo.[^0-9]") "foo.8")))
197-
(should (string-match (lsp-glob-to-regexp "foo.[^0-9]") "foo.f"))
201+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[^0-9]") "foo.5")))
202+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[^0-9]") "foo.8")))
203+
(should (string-match (lsp-glob-convert-to-wrapped-regexp "foo.[^0-9]") "foo.f"))
198204

199205
;; ???: This should properly fail since path-separators should be
200206
;; ignored inside brackets, but here (and in VSCode) it fails for a
@@ -206,7 +212,7 @@
206212
;; way of handling this to recognize that because we're unbalanced
207213
;; at the end, that everything should be treated as a literal. But
208214
;; after experimenting with zsh, this isn't what they use.
209-
(should (not (string-match (lsp-glob-to-regexp "foo[/]bar") "foo/bar"))))
215+
(should (not (string-match (lsp-glob-convert-to-wrapped-regexp "foo[/]bar") "foo/bar"))))
210216

211217
(ert-deftest lsp-file-watch--ignore-list ()
212218
:tags '(no-win)

0 commit comments

Comments
 (0)