Fork me on GitHub

A question for Emacs users... When you connect to CIDER it puts itself at the front of completion-at-point-functions. If CIDER returns any completions, then LSP will never be asked for completions. This gives inconsistent completion behavior based on whether the REPL is running. I don’t see any tools in either CIDER or LSP that would let me configure the completion-at-point priority. I prefer the clojure-lsp completions, so to work around it, I disable CIDER completions like so:

(defun disable-cider-completion ()
  (remove-hook 'completion-at-point-functions #'cider-complete-at-point))
(add-hook 'cider-mode-hook 'disable-cider-completion)
Are there any other approaches? Is it documented anywhere?


It makes it particularly hard to hack on the completion code, because when you jack-in to the LSP nREPL, the completions mostly stop being invoked. That one took awhile to figure out! I was thinking about adding this tip to , but it might be too hidden there.


Yeah, this is a common question and IMO we should add a simple way to configure that either on lsp-mode or cider... Meanwhile the recommend way is to do exactly what you are doing. I have the same config here:


Actually I need to update this guide to match that as well:


Do your LSP completions work fine even with large-ish projects? (> 10k LOC)? It feels so laggy and intermittently unreliable for me


Btw, I've noticed the same thing with Typescript LSP. I wonder if it's my PC/OS/etc


We merged a PR from @U07M2C8TT which improved performance a lot on completion @UR37CBF8D, maybe you can give it a try, check #clojure-lsp-builds


@ericdallo thanks, that’s good to know you’re doing the same thing


@UR37CBF8D I use clojure-lsp completion when working on clojure-lsp itself, which has almost 20K LOC. It’s fast enough for me. A lot can depend on how aggressive your completion settings are. If you have it set to try completion with only 1 character it may get laggy, although the recent changes Eric mentioned may improve that.


Oh right, cool. @ericdallo mind linking the PR from @U07M2C8TT?


@ericdallo it seems the :copy-kondo-configs? false option isn't documented, perhaps that can be added?


I'll add it

gratitude 1


👍 1

When I run make lint-clean locally in clojure-lsp it reports several namespaces that need to be cleaned. But on CI, that lint test hasn’t been failing. Am I missing a config that would make the behavior match?


not really :thinking_face: lint-clean just uses clojure-lsp itself calling clean-ns


@U07M2C8TT try rm .lsp/.cache


No change. It feels like the problem is on CI, not on my machine. The require blocks in those namespaces all include an unused alias to [taoensso.timbre :as log]


we have a custom config to ignore that log


Ahhh! OK, where can I find that config?


check .clj-kondo/config.edn


since log is a ns we use all the time, clojure-lsp/kondo doesn't complain about it with that config


In that case, I’m confused — why doesn’t my make lint-clean use that config? FWIW, Emacs also reports those extra aliases as errors.


that's odd, that config is on project root config, clj-kondo should always bring it


does that happens on master?


Yes. Could I have a global config file that’s overriding the local one?


check ~/.lsp/config.edn (deprecated) and ~/.config/clojure-lsp/config.edn


I have a ~/.lsp/config.edn, but if I rename it, I still get the lint errors


yeah, maybe it's not related indeed


try rm -rf .lsp/.cache && rm -rf .clj-kondo/.cache


Same problem. I’ll try a clean checkout of clojure-lsp

👍 1

also, you are seeing that on latest master right?


Ah, that got rid of the errors. So it must be something cached locally

thinking-face 1

Figured it out. rm -rf lib/.clj-kondo. I’m not sure what I had in there, but it must have been causing problems.


diff -qr bad-dir good-dir FTW


Thanks for your help


hum, interesting, since the project-root is not lib, not sure why that config was being considered


Kinda weird, right? Here’s a minimal reproduction:

❯ mkdir lib/.clj-kondo
❯ make lint-clean


I think this could explain some bugs some users complain from time to time


@U04V15CAJ maybe you can help here, we have this arch:

clojure-lsp (project-root)
- .clj-kondo/config.edn
- lib 
- cli
if we create a lib/.clj-kondo folder it mess up the kondo config from .clj-kondo/config.edn , any clues?


define "mess up"


I'm afk for a few hours


it depends in which directory you lint.


and also what clojure-lsp itself does.


afk now

👍 1

@U07M2C8TT we need to debug the config clojure-lsp is passing to kondo, probably something


@ericdallo sounds good. I’ll look at that

👍 1

Here’s the config that’s passed to clj-kondo.core/run! . It’s generated by . I’ll see what I can learn about these settings and do some experimenting.

{:cache true
   :parallel true
   :copy-configs true
   :lint ["/Users/jmaine/workspace/opensource/clojure-lsp/cli/lib/src:/Users/jmaine/workspace/opensource/clojure-lsp/cli/cli/src:/Users/jmaine/workspace/opensource/clojure-lsp/cli/common-test/src:/Users/jmaine/workspace/opensource/clojure-lsp/cli/lib/test:/Users/jmaine/workspace/opensource/clojure-lsp/cli/cli/test:/Users/jmaine/workspace/opensource/clojure-lsp/cli/src:/Users/jmaine/workspace/opensource/clojure-lsp/cli/resources:/Users/jmaine/workspace/opensource/clojure-lsp/cli/target/lsp-classes:/Users/jmaine/workspace/opensource/clojure-lsp/lib/src:/Users/jmaine/workspace/opensource/clojure-lsp/lib/resources:/Users/jmaine/workspace/opensource/clojure-lsp/cli/scripts"]
   :config {:output {:analysis {:arglists true
                                :locals false
                                :keywords true
                                :protocol-impls true}
                     :canonical-paths true}
            :linters {:unresolved-symbol {:report-duplicates true}
                      :unresolved-namespace {:report-duplicates true}
                      :unresolved-var {:report-duplicates true}}}
   :custom-lint-fn #object[clojure.core$partial$fn__5859 0xabd801f "clojure.core$partial$fn__5859@abd801f"]}


yes, looks correct to me, @U07M2C8TT maybe try to repro with clj-kondo CLI, it's easier for @U04V15CAJ debug later


something like this, example:

clj-kondo --config '{:output {:format :json :analysis {:arglists true :locals false :keywords true}}}' --cache --copy-configs --parallel --lint src test

👍 1

Yes, please provide a clj-kondo only repro and try to prove that clj-kondo is doing something incorrectly, then I will look into it.


Wow... I spent a long time down the wrong path, but I finally understand. When clojure-lsp runs clean-ns from the command line, it first analyzes the full project, using something like this:

(kondo/run! {:lint [project-classpath]})
This part works as expected... there are no :findings of interest, because several linters have been turned off in .clj-kondo/config.edn. This is where I got stuck. I couldn’t figure out why there weren’t any :findings here, but the CLI suggested several namespaces to clean. What I didn’t realize was that after analyzing the full project, clojure-lsp loops through each file individually, analyzing each one more like this:
(with-in-str file-text
  (kondo/run! {:lint ["-"]
               :filename "lib/some/filename.clj"}))
When invoked this way, clj-kondo will pick lib/.clj-kondo as its config directory, because of And since that config directory is empty, all the linters are on by default, and so we get :findings. @ericdallo, this isn’t just a cli problem. Both did-open and did-change follow the same path, linting via stdin with an explicit :filename. That means that users within an editor will also see unexpected lint findings if they have an extra .clj-kondo directory. The only fix I’ve thought of is to force kondo to use the project root config dir:
(with-in-str file-text
  (kondo/run! {:lint ["-"]
               :filename "lib/some/filename.clj"
               :config-dir (str
                            (io/file (shared/uri->filename (:project-root-uri @db/db))
That wouldn’t work for users who store their kondo config somewhere non-standard. Is that a problem?


Amazing finding! Yeah, that is what I meant with users that already complained strange linting on editors, that explains everything now. > That wouldn’t work for users who store their kondo config somewhere non-standard. Is that a problem? Good question, actually until now, I thought that the lint only worked if config was on root, that's why we were always recommending having kondo config on project root when using LSP. It's good to know it works with nested kondo configs, so I see 2 options: • Merge the configs from root until file/folder being linted, not sure if there is a easy way to get that from kondo or we should that manually. • Just ignore nested configs and use root config as we were recommending


Looking at it more, I think #2 is better. Kondo itself doesn’t merge configs. Instead, it picks them according to this priority: 1. If you provide a :config-dir, use it. 2. If you provide a :filename, walk up the directory tree from the file, looking for a .clj-kondo directory. (The name of that directory is not configurable.) 3. Otherwise, start at the directory where the script was invoked (System/getProperty "user.dir"), and follow the same algorithm, walking up looking for .clj-kondo. In all three cases, it uses the first directory it finds. Most of the time the clj-kondo command line will ignore nested .clj-kondo directories, because it takes a lot of extra work to end up in the 2nd case. So, I think that nested .clj-kondo directories are usually a mistake on the user’s part, and they should be advised to move all their config to one root config dir.


makes sense to me


I'm ok with follwoing on ignoring nested and considering only the project root config


BTW we have lsp-clojure-server-info which helps debug what config was chosen


So the correct kondo config dir is stored somewhere in the app db already?


it's the same as project-root, we have a function which brings that on kondo.clj or config.clj I think


Those look pretty good, but they don’t do the “walk up looking for .clj-kondo” algorithm, by clj-kondo.impl.core/config-dir. That might help users who save their kondo config in a parent directory but have their clojure-lsp project root as a subdirectory. Is that a common thing? (I think that kondo handles home/xdg config separately so I’m not as worried about that.) @U04V15CAJ perhaps clj-kondo.impl.core/config-dir could be added to the public API?


Not a common thing @U07M2C8TT, IMO we should get the config from root, if not found we use no config, we can't infer user configured a wrong project root and try to get a correct config, there are multiple cases


OK, that makes sense. I’ll work on a PR. My first attempt, which worked great for my problem, breaks almost all of the tests. 😅


I bet they don’t all set a project root


Yes, not all