Hello, I'd like to use clojure-lsp to get the list of all qualified keywords in my clj project ... I'm using Emacs so i thought that i could reuse current/connected lsp-server db. I've downloaded a fork and connected to lsp-server using
(defun my/connect-to-clojure-lsp-repl ()
"Connect to the running clojure-lsp nREPL server"
(interactive)
(let ((info (lsp-clojure-server-info-raw)))
(when-let (port (and (string-match "\"port\":\\([0-9]+\\)" info)
(match-string 1 info)))
(cider-connect-clj `(:host "localhost" :port ,port)))))
but once i can read @clojure-lsp.db/db* I get lost with db structure and queries 😬
any advices or help that i coudl follow?
thanks in advance!
PS: getting all qualified keywords is first purpose but after that I'd like to query my code to find all calls for foo.my-service/def, where first argument is also a qualified-kw eg : (my-service/def foo xxxx)1. Keep in mind the repl is used for development only, especially because prod binaries are compiled with graaal and that's not possible, also anything inside db can change names and cause breaking changes, the recommended approach is to use https://clojure-lsp.io/api/what-is-it/
2. I believe you can (q/find-keywords db uri) , the clojure-lsp.queries is a useful ns
@ericdallo Thanks for your quick feedback! I think i have also kind of a bug thus my lsp cache db.transit.json file is approx 300 Mb and emacs takes more than 3 mins to generate it ... perhaps my project has edn resources that clj-kondo is including 🤔 or perhaps target folders??
yes, probably, you can check on server logs the classpath considered by clojure-lsp
I'd like to query my code to find all calls for foo.my-service/def, where first argument is also a qualified-kw eg : (my-service/def foo xxxx) i am under the impression that it works like that today. LSP will query and find ALL forms of namespaced keyword. , Destructured etc.
not sure if I followed the best path but here it is how i got it working (using bb, edamame, rewrite-clj ): 1. clj-kondo with
{:analysis {:var-usages true :namespace-definitions true :keywords true}
:output {:format :json :analysis true}}
2. find-function-calls
(defn find-function-calls [analysis-json target-ns target-fn]
(try
(let [analysis (json/parse-string analysis-json true)
var-usages (->> (:analysis analysis)
:var-usages
(filter (fn [{:keys [to name]}]
(and (= (str to) target-ns)
(= (str name) target-fn)))))]
var-usages)
(catch Exception e
(println "Error parsing analysis:" (.getMessage e))
[])))
3. for each usage read the file, find the function seexp, parse it and finally get second item (the qualified keyword)
(defn read-kw-on-second-position [file-ns file line col] 1 reference
(try
(with-open [rdr (io/reader file)]
(let [lines (vec (line-seq rdr))
;; Get lines around the target position
target-line (get lines (dec line) "")
paren-pos (.lastIndexOf target-line "(" (min col (count target-line)))
text-lines (subvec lines (dec line) (min (count lines) (+ line 20)))
text (str/join "\n" text-lines)
text-from-paren (subs text (max 0 paren-pos))
]
(when (System/getenv "DEBUG")
(println "Parsing at" file line col file-ns)
)
(-> (rewrite-clj-parser/parse-string text-from-paren)
(rewrite-clj-node/children )
(nth 2)
(rewrite-clj-node/string )
(eda/parse-string {:auto-resolve {:current file-ns}} )
)))
(catch Exception e
(println "Error parsing form at" file line col "-" (.getMessage e))
nil)))
PS: 😅 I thought that it would be more straightforwardglad you made it work, but you are doing what clojure-lsp does (and more) under the hood, which should be possible too
well i thought that i should start with clojure-lsp to build on top of it but i couldn't following docs 😬 I'd love to keep trying anyway
maybe we could add examples in docs indeed
I listed 3 steps, which ones could clojure-lsp do? ... perhaps I'm doing more steps 😅 too
1. clojure-lsp already does by default
2. (clojure-lsp.queries/find-references ...) or maybe via clojure-lsp.api
3. should be done on your side but not parsing with rewrite-clj, probably using the analysis clojure-lsp provide
sounds great, is there any clojure-lsp.queries/find-references examples for function calks? or clojure-lsp.api?
the clojure-lsp project itself uses a lot clojure-lsp.queries for all features, this is the best we have so far, we may want to add to the docs more examples
ok, I'll try to find the good parts and try to contribute to the repo too 🙂 thanks a lot!
cool, thanks
BTW: I love LSP & clj-lsp!
Currently, the organize imports code action reformats ns forms from this style:
(ns foo
(:require [foo.bar]))
To this style:
(ns foo
(:require
[foo.bar]))
I like allowing clojure-lsp to manage and organize imports otherwise, but this reformatting can result in disruptively large whitespace diffs in existing codebases. Is there any way to prevent it from happening? If not, would y'all be open to changing this behavior?I create a specific format / blank space git commit (without business or technical changes). I find this much simpler in the long run.
you can customize that with https://clojure-lsp.io/settings/#ns-inner-blocks-indentation
Hi again 🙂 trying to use clojure-lsp from bb i get cyclic dependency error here https://github.com/clojure-lsp/clojure-lsp/blob/master/lib/src/clojure_lsp/shared.clj#L5 my bb.edn
{:deps {borkdude/edamame {:mvn/version "1.0.0"}
rewrite-clj/rewrite-clj {:mvn/version "1.2.50"}
com.github.clojure-lsp/clojure-lsp {:mvn/version "2025.06.06-19.04.49"}
}}
Type: clojure.lang.ExceptionInfo
Message: Cyclic load dependency: clojure-lsp.db->clojure-lsp.config->[ clojure-lsp.shared ]->[ clojure-lsp.shared ]
Data: {:type :sci/error, :line nil, :column nil, :file "clojure_lsp/shared.clj"}
Location: clojure_lsp/shared.clj:2:3
----- Context ------------------------------------------------------------------
1: (ns clojure-lsp.shared
2: (:require
^--- Cyclic load dependency: clojure-lsp.db->clojure-lsp.config->[ clojure-lsp.shared ]->[ clojure-lsp.shared ]
3: [babashka.fs :as fs]
4: [clojure-lsp.logger :as logger]
5: [clojure-lsp.shared :as shared]
6: [clojure.core.async :refer [<! >! alts! chan go-loop timeout]]
7: [ :as io]
BTW: also tried babashka pod (2024.04.22-11.50.26) but perhaps not aligned with clojure-lsp.api thus i got "Could not resolve symbol: lsp-api/references"
that's because of this self-requiring namespace here: https://github.com/clojure-lsp/clojure-lsp/blob/e8d078f7bafda75a6bf2f09722ea79fee3b6ecc3/lib/src/clojure_lsp/shared.clj#L5 perhaps SCI can allow this, but perhaps it's not necessary to do this at all?
anyway, most of clojure-lsp isn't bb-compatible I think so you'll have to use the pod. I'm sure it can be updated
hum yes, we may need to update the pod
in the registry you mean right?
yes!