Any opinions what is best way to sort JS lib requires where letter case might affect the sort?
• Cljstyle: uppercase letters are sorted first, no option to change
• Clj-kondo/clojure-lsp (clean-ns): letter case is ignored and MUI styles ns is sorted together with components starting with S, no option to change
• Clj-kondo :unsorted-required-namespaces is off by default (the project has the linter enabled, and some ns disable it to hide warnings from mui styles require)
• Cljfmt/clojure-lsp (format) doesn't sort requires by default, you need to enable :sort-ns-references?, upper case letters are sorted first, same as cljstyle! Differs from clean-ns!
• Though the project uses cljstyle, I'd like to be able to use clean-ns from clojure-lsp in the editor
This has frustrated me for long time, but I'm not even sure which which project(s) to open issue at. Now that I see lsp clean-ns and format work differently, I think clj-kondo and clean-ns should match the cljfmt sort.
:unsorted-required-namespaces {:level :warning
:sort :lexicographically}
@borkdude
:sort key ok? Should we specify what is the "default" value or do we just support this value and all other values / unset ignores case?let's just do whatever clojure-lsp has?
(haven't checked)
:sort {:require true/false/:lexicographically}
so it doesn't quite fit to clj-kondo config
why not?
Well clj-kondo already has the :level option to toggle if the linter is enabled or not, but we can't use the level to also control how the sort should happen
can you link me to the config that clojure-lsp uses?
I have trouble finding it in their docs
false disables the sorting completely, true enables with default sorting, :lexicographically enables with different sorting
ah yes
this looks good to me: https://clojurians.slack.com/archives/CPABC1H61/p1727168192733539?thread_ts=1726138636.590879&cid=CPABC1H61
the default, let's not change it as it is now, but also give it a name
:default?
that's not a good name
True 😄
(Lunch now, will be back in moment, I have tests written already.)
lexicographically-lowercased
or case-insensitive?something like that. thanks!
Do linters validate the options values generally?
Or is there some schema for the options?
there is a built-in linter that does some of this
Done: https://github.com/clj-kondo/clj-kondo/pull/2399/files
Though lexicographically matches clojure-lsp, I wonder if it would be more obvious to just call these :case-sensitive and :case-insensitive/`:lower-cased` or something
I wonder if the clojure-lsp :lexicographically also has some other differences vs. just the case? "to do a lexicographic sort that places unwrapped namespaces last."
yeah probably that's a better name
I like case-(in)sensitive better than lower-cased
I'll update the PR to that 👍
I think the clj-kondo way matches what emacs / CIDER / clj-refactor did . Can you paste the code, then I can test what it did
(ns foo
(:require ["@mui/material/Avatar$default" :as Avatar]
["@mui/material/Stack$default" :as Stack]
["@mui/material/Tab$default" :as Tab]
["@mui/material/Tabs$default" :as Tabs]
["@mui/material/Typography$default" :as Typography]
["@mui/material/styles" :as styles]
["moment/src/moment$default" :as moment]))The difference between lsp clean-ns and format isn't obvious because it requires one to turn on cljfmt :sort-ns-references?, and similar require forms which likely doesn't happen unless you use some JS libs
clojure-sort-ns says the above ns form is already sorted
in emacs
so that is same as cljfmt and cljstyle
clj-kondo and clojure-lsp clean-ns differ from that
how does clj-kondo complain about this then? I don't see it
❯ clj-kondo --config '{:linters {:unsorted-required-namespaces {:level :warning}}}' --lint foo.cljs
foo.cljs:4:14: warning: Unsorted namespace: @mui/material/styles
linting took 8ms, errors: 0, warnings: 1ah yes, I do see it:
src/foo.cljs:7:14: warning: Unsorted namespace: @mui/material/stylesso it should behave case-sensitive, right?
I think so. I think for MUI case it makes sense to separate the utility file from the components, like their naming does.
alright, issue welcome. no clue why clj-kondo disregards case
the lsp clean-ns issue is probably independent
👍 I'll start from clj-kondo
There is a test case that sort is case insensitive, test/clj_kondo/main_test.clj line 2933
How do other tools handle symbols? Could there be different between symbol and string sort
aha hmm: https://github.com/clj-kondo/clj-kondo/commit/02d6fe76352cb852d7a56ddafdc54b23f9a82edb
oh the issue was: https://github.com/clj-kondo/clj-kondo/issues/1718 "this aligns better with clojure-lsp"
hmm
cc @ericdallo @dpsutton @snoe I'm open to changing this, it doesn't make sense to me immediately, but perhaps y'all remember why we did this?
cljfmt wants to sort Bar before bar (if the sort option is enabled)
yeah, there seems to be a conflict here
maybe that commit was to match with lsp clean-ns, but formatting tools weren't considered at that time
clojure-sort ns also sorts Boo in front of boo
ping @ericdallo @dpsutton @snoe. If I don't hear back what is the rationale to divert from other clojure tools with respect to sorting ns forms, I'll probably revert to whatever the other main tools are doing, since sorting case insensitively doesn't make sense to me.
I lost that msg, will take a look
Thanks! Github issue here: https://github.com/clj-kondo/clj-kondo/issues/2394
@juhoteperi I think using:
.lsp/config.edn
{:clean {:sort {:require :lexicographically}}}
makes the sorting equals to what you want, is that enough for clojure-lsp?
https://clojure-lsp.io/settings/#requireAha yes. That does seem to fix clojure-lsp part of this.
I didn't connect the documentation to this case.
true mentions sort according to the Clojure Style Guide but I don't know if that is the case? (Not sure if Style Guide has an example for this case)
yeah, I don't think it has, we can improve the docs
i don’t remember any context unfortunately. This stuff gets so tricky and can be a really sharp pain for no real reason. I wish i remembered the motivating example originally.
What I could do is remove the case insensitivity and wait for that context to come back ;)
100%. Turn it off and see who complains 🙂
I think clj-kondo and clojure-lsp should be aligned as otherwise we will have clj-kondo complaining and clojure-lsp sorting differently which seems worst than current behavior
clj-kondo also (at least originally) aligns with other clojure tools like clojure-mode in emacs though
and cljfmt
and cljfmt is used in clojure-lsp which seem not to align by default, so maybe it's clojure-lsp that should change the default
yeah, I think so, I just not sure if changing that config will add other side effects, but agree
oh i think i remember now. The casing stuff just feels awkward. I think it was in imports
(:import
(org.A Klass)
(org.G Klass)
(org.X Klass)
(org.a Klass)
(org.g Klass))
it’s really annoying that the entire upper case comes before the entire lowercase. Because you can’t quickly scan for the import you need, you have to remember the casing.Luckily I think this sorting only matters for people who
• use JS libs
• use JS libs with file naming conventions with both lower and upper case letters
• use specific files from those libs so the letter case matters
I haven't seen any other cases where tools would sort requires different than this @mui/material/styles
so this is “correctly” lexicographically sorted and you have to remember casing to quickly find your imports.
ok so maybe clj-kondo just needs to add an option :lexicographically then as well, to make it behave case insensitive?
PR welcome