This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-15
Channels
- # announcements (8)
- # architecture (9)
- # autochrome-github (1)
- # babashka (48)
- # beginners (55)
- # calva (36)
- # cider (16)
- # clj-commons (1)
- # clj-kondo (38)
- # cljs-dev (44)
- # cljsrn (1)
- # clojure (164)
- # clojure-europe (35)
- # clojure-nl (2)
- # clojure-norway (10)
- # clojure-uk (23)
- # clojurescript (50)
- # conjure (24)
- # core-async (1)
- # cryogen (2)
- # cursive (38)
- # datalevin (11)
- # datascript (2)
- # datomic (13)
- # duct (1)
- # emacs (16)
- # events (12)
- # exercism (3)
- # figwheel-main (7)
- # fulcro (26)
- # honeysql (5)
- # integrant (1)
- # jobs (3)
- # kaocha (6)
- # lsp (72)
- # malli (22)
- # nextjournal (35)
- # nrepl (1)
- # off-topic (34)
- # pathom (5)
- # polylith (8)
- # portal (40)
- # re-frame (14)
- # reagent (42)
- # reitit (1)
- # releases (1)
- # remote-jobs (1)
- # reveal (9)
- # sci (2)
- # shadow-cljs (13)
- # sql (3)
- # tools-deps (33)
- # vim (25)
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 development.md
, 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: https://github.com/ericdallo/dotfiles/blob/master/.doom.d/config.el#L57
Actually I need to update this guide to match that as well: https://emacs-lsp.github.io/lsp-mode/tutorials/clojure-guide/
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?
Yeah, my bad, it should be on https://clojure-lsp.io/settings/
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]
Ahhh! OK, where can I find that config?
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
Yes. Could I have a global config file that’s overriding the local one?
I have a ~/.lsp/config.edn
, but if I rename it, I still get the lint errors
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
@U04V15CAJ maybe you can help here, we have this arch:
clojure-lsp (project-root)
- .clj-kondo/config.edn
- lib
src
test
...
- cli
src
test
...
if we create a lib/.clj-kondo
folder it mess up the kondo config from .clj-kondo/config.edn
, any clues?it ignores https://github.com/clojure-lsp/clojure-lsp/blob/master/.clj-kondo/config.edn#L6
@U07M2C8TT we need to debug the config clojure-lsp is passing to kondo, probably something https://github.com/clojure-lsp/clojure-lsp/blob/master/lib/src/clojure_lsp/kondo.clj#L164
Here’s the config that’s passed to clj-kondo.core/run!
. It’s generated by https://github.com/clojure-lsp/clojure-lsp/blob/ca1621ba7f8475095f2bf74d895411372debf4f4/lib/src/clojure_lsp/kondo.clj#L146 . 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
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 https://github.com/clj-kondo/clj-kondo/blob/919478cdfc58b47dd48a7383c9b3a6de2b507b1f/src/clj_kondo/core.clj#L107. 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))
".clj-kondo"))}))
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.
I'm ok with follwoing on ignoring nested and considering only the project root config
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, https://github.com/clj-kondo/clj-kondo/blob/44fa20c186fa3f038b8777a8c2456678d08d25f9/src/clj_kondo/impl/core.clj#L179-L198 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