From b022e2842900586a9008ec3a3036c39441097938 Mon Sep 17 00:00:00 2001
From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
Date: Sat, 1 Mar 2025 11:56:21 +0000
Subject: [PATCH] Remove completion with no labels and filterText

---
 lsp-completion.el | 135 ++++++++++++++++++++++------------------------
 1 file changed, 65 insertions(+), 70 deletions(-)

diff --git a/lsp-completion.el b/lsp-completion.el
index 1943791bfd..27fa4c7ea4 100644
--- a/lsp-completion.el
+++ b/lsp-completion.el
@@ -287,7 +287,7 @@ Returns unresolved completion item detail."
 
 (defvar lsp-completion--cache nil
   "Cached candidates for completion at point function.
-In the form of plist (prefix-pos items :lsp-items :prefix ...).
+In the form of plist (prefix-pos items :prefix ...).
 When the completion is incomplete, `items' contains value of :incomplete.")
 
 (defvar lsp-completion--last-result nil
@@ -334,62 +334,47 @@ Return `nil' when fails to guess prefix."
 
 (defun lsp-completion--to-internal (items)
   "Convert ITEMS into internal form."
-  (--> items
-    (-map (-lambda ((item &as &CompletionItem
-                          :label
-                          :filter-text?
-                          :_emacsStartPoint start-point
-                          :score?))
-            `( :label ,(or (unless (lsp-falsy? filter-text?) filter-text?) label)
-               :item ,item
-               :start-point ,start-point
-               :score ,score?))
-          it)))
-
-(cl-defun lsp-completion--filter-candidates (items &key
-                                                   lsp-items
-                                                   markers
-                                                   prefix
-                                                   &allow-other-keys)
-  "List all possible completions in cached ITEMS with their prefixes.
-We can pass LSP-ITEMS, which will be used when there's no cache.
-The MARKERS and PREFIX value will be attached to each candidate."
-  (lsp--while-no-input
-    (->>
-     (if items
-         (--> (let (queries fuz-queries)
-                (-keep (-lambda ((cand &as &plist :label :start-point :score))
-                         (let* ((query (or (plist-get queries start-point)
-                                           (let ((s (buffer-substring-no-properties
-                                                     start-point (point))))
-                                             (setq queries (plist-put queries start-point s))
-                                             s)))
-                                (fuz-query (or (plist-get fuz-queries start-point)
-                                               (let ((s (lsp-completion--regex-fuz query)))
-                                                 (setq fuz-queries
-                                                       (plist-put fuz-queries start-point s))
-                                                 s)))
-                                (label-len (length label))
-                                (case-fold-search completion-ignore-case))
-                           (when (string-match fuz-query label)
-                             (put-text-property 0 label-len 'match-data (match-data) label)
-                             (plist-put cand
-                                        :sort-score
-                                        (* (or (lsp-completion--fuz-score query label) 1e-05)
-                                           (or score 0.001)))
-                             cand)))
-                       items))
-              (if lsp-completion--no-reordering
-                  it
-                (sort it (lambda (o1 o2)
-                           (> (plist-get o1 :sort-score)
-                              (plist-get o2 :sort-score)))))
-              ;; TODO: pass additional function to sort the candidates
-              (-map (-rpartial #'plist-get :item) it))
-       lsp-items)
-     (-map (lambda (item) (lsp-completion--make-item item
-                                                     :markers markers
-                                                     :prefix prefix))))))
+  (-map (-lambda ((item &as &CompletionItem
+                        :label
+                        :_emacsStartPoint start-point
+                        :score?))
+          `( :label ,label
+             :item ,item
+             :start-point ,start-point
+             :score ,score?))
+        items))
+
+(defun lsp-completion--filter-candidates (items)
+  "List all possible completions in cached ITEMS with their prefixes."
+  (--> (let (queries fuz-queries)
+         (-keep (-lambda ((cand &as &plist :label :start-point :score))
+                  (let* ((query (or (plist-get queries start-point)
+                                    (let ((s (buffer-substring-no-properties
+                                              start-point (point))))
+                                      (setq queries (plist-put queries start-point s))
+                                      s)))
+                         (fuz-query (or (plist-get fuz-queries start-point)
+                                        (let ((s (lsp-completion--regex-fuz query)))
+                                          (setq fuz-queries
+                                                (plist-put fuz-queries start-point s))
+                                          s)))
+                         (label-len (length label))
+                         (case-fold-search completion-ignore-case))
+                    (when (string-match fuz-query label)
+                      (put-text-property 0 label-len 'match-data (match-data) label)
+                      (plist-put cand
+                                 :sort-score
+                                 (* (or (lsp-completion--fuz-score query label) 1e-05)
+                                    (or score 0.001)))
+                      cand)))
+                items))
+       (if lsp-completion--no-reordering
+           it
+         (sort it (lambda (o1 o2)
+                    (> (plist-get o1 :sort-score)
+                       (plist-get o2 :sort-score)))))
+       ;; TODO: pass additional function to sort the candidates
+       (-map (-rpartial #'plist-get :item) it)))
 
 (defconst lsp-completion--kind->symbol
   '((1 . text)
@@ -589,9 +574,13 @@ Returns resolved completion item details."
                      ((or done? result) result)
                      ((and (not lsp-completion-no-cache)
                            same-session?
-                           (listp (cl-second lsp-completion--cache)))
-                      (setf result (apply #'lsp-completion--filter-candidates
-                                          (cdr lsp-completion--cache))))
+                           (cl-second lsp-completion--cache))
+                      (setf result (cl-destructuring-bind (_ items &key markers prefix) lsp-completion--cache
+                                     (-map
+                                      (lambda (item)
+                                        (lsp-completion--make-item item :markers markers :prefix prefix))
+                                      (lsp--while-no-input
+                                        (lsp-completion--filter-candidates items))))))
                      (t
                       (-let* ((resp (lsp-request-while-no-input
                                      "textDocument/completion"
@@ -614,7 +603,12 @@ Returns resolved completion item details."
                                                              :_emacsStartPoint
                                                              (or (lsp-completion--guess-prefix item)
                                                                  bounds-start)))
-                                                  it))))
+                                                  it)
+                                            ;; remove items with no label and filterText
+                                            (-remove
+                                             (-lambda ((&CompletionItem :filter-text? :label))
+                                               (and (lsp-falsy? filter-text?) (lsp-falsy? label)))
+                                             it))))
                               (markers (list bounds-start (copy-marker (point) t)))
                               (prefix (buffer-substring-no-properties bounds-start (point)))
                               (lsp-completion--no-reordering (not lsp-completion-sort-initial-results)))
@@ -625,17 +619,18 @@ Returns resolved completion item details."
                                                            ((and done? (not (seq-empty-p items)))
                                                             (lsp-completion--to-internal items))
                                                            ((not done?) :incomplete))
-                                                          :lsp-items nil
                                                           :markers markers
                                                           :prefix prefix)
-                              result (lsp-completion--filter-candidates
-                                      (cond (done?
-                                             (cl-second lsp-completion--cache))
-                                            (lsp-completion-filter-on-incomplete
-                                             (lsp-completion--to-internal items)))
-                                      :lsp-items items
-                                      :markers markers
-                                      :prefix prefix))))))
+                              result (-map
+                                      (lambda (item)
+                                        (lsp-completion--make-item item :markers markers :prefix prefix))
+                                      ;; Prevent company from flickering. See #2148.
+                                      (lsp--while-no-input
+                                        (->> (if (or (and done? (cl-second lsp-completion--cache))
+                                                     (and lsp-completion-filter-on-incomplete
+                                                          (lsp-completion--to-internal items)))
+                                                 (lsp-completion--filter-candidates items)
+                                               items)))))))))
                 (:interrupted lsp-completion--last-result)
                 (`,res (setq lsp-completion--last-result res))))))
       (list