emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/eglot c34ec42 2/8: Per #645: Attempt to speed up initia


From: Stefan Monnier
Subject: [elpa] externals/eglot c34ec42 2/8: Per #645: Attempt to speed up initial directory/glob correspondence
Date: Wed, 14 Apr 2021 18:53:07 -0400 (EDT)

branch: externals/eglot
commit c34ec4218c7d4ab7c4a7e1643c76c30cb70978ab
Author: João Távora <joaotavora@gmail.com>
Commit: João Távora <joaotavora@gmail.com>

    Per #645: Attempt to speed up initial directory/glob correspondence
    
    In #602, not only a new glob processing system was implemented, but
    also a new, more correct, way to look for directories that might hold
    files matched by one of these globs.
    
    Answering this question is important because the file watchers for
    'workspace/didChangeWatchedFiles' are placed on a per-directory basis.
    Previously, a glob such as /foo/**/bar/*.el would fail to produce
    practical file-watching effects because /foo/**/bar/ isn't really a
    directory.
    
    However, answering this question is also expensive, as the globs sent
    by the LSP server are meant to match files, not directories.  The only
    way is to list all files under the project's root directory and test
    each glob on each one.  If it matches at least one file, that file's
    directory is meant to be watched.
    
    We suspect that in #645 and #633 we are falling victim to LSP server
    who serve a tremendous unoptimized number of globs, one for each file.
    So instead of sending just '/foo/**/bar/*.el' they send
    '/foo/**/bar/quux.el', '/foo/**/bar/quuz.el', etc...  which would
    tremendeously slow down the process.  But this is only a suspicion.
    
    This commit tries some simple optimizations: if a directory is known
    to be watch-worthy becasue one of its files matched a single glob, no
    more files under that directory are tried.  This should help somewhat.
    
    Also fixed a bug in 'eglot--files-recursively', though I suspect that
    doesn't make that much of a difference.
    
    * eglot.el (eglot--directories-matched-by-globs): New helper.
    (eglot--files-recursively): Fix bug.
---
 eglot.el | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/eglot.el b/eglot.el
index c236388..59804da 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2674,10 +2674,7 @@ at point.  With prefix argument, prompt for ACTION-KIND."
                    (eglot--glob-compile globPattern t t))
                  watchers))
          (dirs-to-watch
-          (cl-loop for f in (eglot--files-recursively)
-                   when (cl-loop for g in globs thereis (funcall g f))
-                   collect (file-name-directory f) into dirs
-                   finally (cl-return (delete-dups dirs)))))
+          (eglot--directories-matched-by-globs default-directory globs)))
     (cl-labels
         ((handle-event
           (event)
@@ -2784,9 +2781,23 @@ If NOERROR, return predicate, else erroring function."
         (cl-loop with default-directory = dir
                  with completion-regexp-list = '("^[^.]")
                  for f in (file-name-all-completions "" dir)
-                 if (file-name-directory f) append (eglot--files-recursively f)
+                 if (file-directory-p f) append (eglot--files-recursively f)
                  else collect (expand-file-name f))))
 
+(defun eglot--directories-matched-by-globs (dir globs)
+  "Discover subdirectories of DIR with files matched by one of GLOBS.
+Each element of GLOBS is either an uncompiled glob-string or a
+compiled glob."
+  (setq globs (cl-loop for g in globs
+                       collect (if (stringp g) (eglot--glob-compile g t t) g)))
+  (cl-loop for f in (eglot--files-recursively dir)
+           for fdir = (file-name-directory f)
+           when (and
+                 (not (member fdir dirs))
+                 (cl-loop for g in globs thereis (funcall g f)))
+           collect fdir into dirs
+           finally (cl-return (delete-dups dirs))))
+
 
 ;;; Rust-specific
 ;;;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]