-
-
Notifications
You must be signed in to change notification settings - Fork 149
/
workspace_symbols.clj
64 lines (59 loc) · 2.25 KB
/
workspace_symbols.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(ns clojure-lsp.feature.workspace-symbols
(:require
[anonimitoraf.clj-flx :as flx]
[clojure-lsp.feature.document-symbol :as f.document-symbol]
[clojure-lsp.queries :as q]
[clojure-lsp.shared :as shared]
[clojure.string :as string]))
(set! *warn-on-reflection* true)
(defn ^:private fuzzy-search [^String query col get-against]
(let [query (string/lower-case query)]
(->> (for [doc col]
{:data doc
:score (flx/score query (string/lower-case (name (get-against doc))))})
(filter #(not (nil? (:score %))))
(sort-by :score (comp - compare))
(map :data))))
(defn ^:private fuzzy-filter
[query elements]
(if (string/blank? query)
elements
(fuzzy-search query elements :name)))
(defn ^:private group-by-ord
"Similar to `group-by` but returns a vector of the groups
without the keys.
Use this fn if the order of the groups needs to be preserved.
The order of groups depends on the order of their respective
first members."
[f coll]
(->> coll
(reduce (fn [groups curr]
(let [group-key (f curr)
group-idx (->> groups
(map-indexed (fn [idx g] {:idx idx :group g}))
(filter #(= group-key (-> % :group :key)))
first
:idx)]
(if (nil? group-idx)
(conj groups {:key group-key :members [curr]})
(update-in groups [group-idx :members] conj curr))))
[])
(map :members)))
(defn workspace-symbols [query db]
;; TODO refactor to be a complete transducer
(->> (into {}
(comp
(q/filter-project-analysis-xf db))
(:analysis @db))
vals
flatten
(filter f.document-symbol/declaration?)
(fuzzy-filter query)
(mapv (fn [element]
{:name (-> element :name name)
:kind (f.document-symbol/element->symbol-kind element)
:location {:uri (shared/filename->uri (:filename element) db)
:range (shared/->scope-range element)}}))
(group-by-ord (comp :uri :location))
flatten
(into [])))