lsp

borkdude 2025-11-18T12:03:03.675949Z

It seems one can't navigate to an inner class which is denoted with a dollar in the middle: Foo$Bar

ericdallo 2025-11-18T12:03:57.211399Z

Indeed, this was never implemented but always bug me, would you mind create a issue about it? it should not be that hard to parse that and try to find a class, or maybe we can solve somehow on kondo

borkdude 2025-11-18T12:20:55.032709Z

https://github.com/clojure-lsp/clojure-lsp/issues/2157

ericdallo 2025-11-18T12:40:33.932709Z

@borkdude taking a look at that, I found that there is a one line fix in kondo that could make that work, but I wanna know if there was reason for it:

ericdallo 2025-11-18T12:41:02.222329Z

it seems kondo add to :java-class-definitions the :class with inner class separated by . instead of $

ericdallo 2025-11-18T12:41:33.356149Z

example: :class my_package.Foo.Bar instead of my_package.Foo$Bar , so when clojure-lsp compares it doesn't match

ericdallo 2025-11-18T12:42:11.816769Z

it's weird because java-class-usages does use Foo$Bar in its class field

ericdallo 2025-11-18T12:42:47.911449Z

I can do a replace-all . -> $ in clojure-lsp, but looks to me that this inconsistency should be fixed on kondo, WDYT

ericdallo 2025-11-18T12:45:16.039959Z

actually the replace is tricky as I don't know what is class and what is package: my.package.Foo.Bar , maybe only checking upper case letters

borkdude 2025-11-18T12:52:56.642459Z

yeah I don't know why we did that. feel free to change it, I don't think it will be important to preserve that

๐Ÿ‘ 1
ericdallo 2025-11-18T13:03:48.265789Z

hum, I think we might not be outputing java-class-definitions for inner class in kondo too

ericdallo 2025-11-18T13:12:44.996529Z

not really:

$ clj -M:clj-kondo/dev --lint ~/dev/clojure-lsp/lib/test/fixtures/java_interop/Parent.java --config '{:output {:format :edn :analysis {:java-class-definitions true}}}' | jet -t ':analysis :java-class-definitions'

[{:class "my_class.Parent",
  :uri "file:/home/greg/dev/clojure-lsp/lib/test/fixtures/java_interop/Parent.java",
  :filename "/home/greg/dev/clojure-lsp/lib/test/fixtures/java_interop/Parent.java",
  :flags #{}}
 {:class "my_class.Parent.Child",
  :uri "file:/home/greg/dev/clojure-lsp/lib/test/fixtures/java_interop/Parent.java",
  :filename "/home/greg/dev/clojure-lsp/lib/test/fixtures/java_interop/Parent.java",
  :flags #{}}]

borkdude 2025-11-18T13:14:09.509139Z

so it does report the inner class right? just not with dollar

ericdallo 2025-11-18T13:14:18.258909Z

yes

borkdude 2025-11-18T13:14:27.207429Z

and why no line/col number?

ericdallo 2025-11-18T13:14:43.302899Z

yeah, good question, I think we never managed to get those on kondo side

ericdallo 2025-11-18T13:14:46.931339Z

but would be nice to have them

ericdallo 2025-11-18T13:14:55.307879Z

otherwise navigation will always to top of file

ericdallo 2025-11-18T13:14:59.847809Z

which for inner class is not cool

borkdude 2025-11-18T13:15:02.811269Z

especially for inner classes yes

ericdallo 2025-11-18T13:15:32.683089Z

I will check why it's not working in clojure-lsp side the inner class definition even replacing the $

borkdude 2025-11-18T13:17:03.619739Z

you should only replace the last .

borkdude 2025-11-18T13:17:30.453319Z

I guess it's ambiguous since foo.bar.Baz could be Baz in a package foo.bar or Baz could be an inner class of foo.bar

ericdallo 2025-11-18T13:17:37.353779Z

yeah, I did the other way around for now:

(string/replace (:class java-class-usage) "$" ".")
replacing the java-class-usage instead for quick check

borkdude 2025-11-18T13:17:52.983669Z

so we really need to fix it in clj-kondo because of ambiguity

ericdallo 2025-11-18T13:17:59.089889Z

yes

ericdallo 2025-11-18T13:19:23.820089Z

nope

borkdude 2025-11-18T13:20:43.144309Z

I don't know man. Don't you have AI tools for this? ;P

๐Ÿ˜‚ 1
๐Ÿ˜ฎ 1
ericdallo 2025-11-18T13:20:54.677939Z

๐Ÿ˜‚ yeah, I can try that

ericdallo 2025-11-18T13:23:19.272299Z

found it

ericdallo 2025-11-18T13:23:23.447289Z

(ECA found it he)

ericdallo 2025-11-18T13:23:55.448559Z

so we may want to replace there

borkdude 2025-11-18T13:26:29.525849Z

how do you know it's an inner class there?

ericdallo 2025-11-18T13:26:52.248859Z

that's what I'm looking right now

ericdallo 2025-11-18T14:52:22.509869Z

reviewplease https://github.com/clj-kondo/clj-kondo/pull/2657

borkdude 2025-11-18T15:10:00.971039Z

the normalize-inner-class-names looks really complicated. why isn't it just a matter of replacing the last dot with a dollar?

borkdude 2025-11-18T15:10:24.238949Z

package names can have capital letters too, class names can be all lowercase

ericdallo 2025-11-18T15:10:26.568539Z

what function can I use to replace the last?

ericdallo 2025-11-18T15:10:33.675419Z

also, what about multiple inner classes

borkdude 2025-11-18T15:10:35.801929Z

so relying on that isn't accurate

ericdallo 2025-11-18T15:10:38.653579Z

Foo$Bar$Baz

ericdallo 2025-11-18T15:11:00.904719Z

hum, if class names can be lower case so we have a problem indeed

borkdude 2025-11-18T15:11:14.089169Z

they usually aren't but they can

borkdude 2025-11-18T15:11:35.563519Z

can you get to the package name of the class? if you have that, then the rest is dollars

borkdude 2025-11-18T15:11:41.286829Z

or the parent class

ericdallo 2025-11-18T15:11:49.506269Z

I think so

ericdallo 2025-11-18T15:26:50.239979Z

we use asm for .class and javaparser for .java

borkdude 2025-11-18T15:27:11.611779Z

yes, your PR was about asm right

borkdude 2025-11-18T15:27:26.817339Z

oh I see now

borkdude 2025-11-18T15:27:31.506979Z

it was javaparser

borkdude 2025-11-18T15:27:50.277589Z

so we need an additional fix for ASM I guess

ericdallo 2025-11-18T15:28:02.361129Z

I got the package, and made this:

(defn ^:private normalize-inner-class-names "Replace the . of full-class-name after package-name with $ Example: full-class-name: my.custom.package.Foo.Bar.Baz packcage-name: my.custom.package -> my.custom.package.Foo$Bar$Baz" [full-class-name package-name] (let [prefix (when-not (str/blank? package-name) (str package-name "."))] (if (and prefix (not (str/starts-with? full-class-name prefix))) ;; If the full-class-name doesn't start with the given package-name, ;; leave it unchanged. full-class-name (let [rest-name (if prefix (subs full-class-name (count prefix)) full-class-name) segments (str/split rest-name #"\.") [top & inners] segments] (if (empty? inners) ;; No inner classes to normalize. full-class-name ;; Rebuild name with $ between inner class segments. (str (or prefix "") top "$" (str/join "$" inners)))))))``` but looks complex yet

ericdallo 2025-11-18T15:28:15.744309Z

ASM seems to output as $ already

ericdallo 2025-11-18T15:28:34.981489Z

I'd say it was just javaparser bad choice

borkdude 2025-11-18T15:29:34.891249Z

ok

borkdude 2025-11-18T15:30:06.876199Z

good work

ericdallo 2025-11-18T15:30:26.768719Z

thanks, do you see any way to make simpler that code?

borkdude 2025-11-18T15:32:28.949349Z

I think I do. If you know the package name, you can just "substract" that from the full class name, replace dots with $ and be done?

borkdude 2025-11-18T15:32:50.783089Z

you don't first have to split the class name

ericdallo 2025-11-18T15:33:29.663679Z

ah of course, sounds simpler indeed, let me try

ericdallo 2025-11-18T15:37:54.391639Z

way better :)

(defn ^:private normalize-inner-class-names
  "Replace the . of full-class-name after package-name with $
   Example:
     full-class-name: my.custom.package.Foo.Bar.Baz
     packcage-name: my.custom.package
  
     -> my.custom.package.Foo$Bar$Baz"
  [full-class-name package-name]
  (let [prefix (if (string/blank? package-name)
                 ""
                 (str package-name "."))
        class-name (subs full-class-name (count prefix) (count full-class-name))
        class-name (str/replace class-name "." "$")]
    (str prefix class-name)))

borkdude 2025-11-18T15:49:52.013649Z

indeed :)

borkdude 2025-11-18T16:05:44.067569Z

hmm, I still can't navigate to the class

borkdude 2025-11-18T16:05:53.904329Z

I threw away my .clj-kondo directory

borkdude 2025-11-18T16:06:31.098019Z

I'll also throw away .lsp cache

borkdude 2025-11-18T16:06:47.189619Z

nope, still no luck

borkdude 2025-11-18T16:06:59.738189Z

so maybe something has to be changed on lsp as well?

ericdallo 2025-11-18T16:07:07.492019Z

yeah, I think the issue might be on clojure-lsp side, I'm still investigating

ericdallo 2025-11-18T16:25:32.127469Z

Hum, I think there is still something to fix on kondo, when linting a jar, example:

clj -M:clj-kondo/dev --lint ~/.m2/repository/org/benf/cfr/0.152/cfr-0.152.jar --config '{:output {:format :edn :analysis {:java-class-definitions true :java-member-definitions true :java-class-usages true}}}' | jet -t ':analysis :java-class-definitions'
I do not get the inner classes, like CfrDriver$Builder

ericdallo 2025-11-18T16:25:53.082719Z

it might be an ASM issue now, since this jar has .class

borkdude 2025-11-18T16:26:25.593489Z

do you mean, without the package name?

ericdallo 2025-11-18T16:26:50.646879Z

no, a different issue, I'm checking but I think kondo is ignoring inner classes when looping the jar class files

borkdude 2025-11-18T16:27:05.659339Z

could be. then we need visitInnerClass

ericdallo 2025-11-18T16:27:15.628169Z

hum, maybe

borkdude 2025-11-18T16:27:15.933219Z

if it's not there yt

ericdallo 2025-11-18T16:27:48.531719Z

yeah, there is no visitInnerClass being used

ericdallo 2025-11-18T16:28:49.454969Z

I think we indeed need to implement visitInnerClass

ericdallo 2025-11-18T16:28:55.248129Z

will try to create a test for that

borkdude 2025-11-18T16:29:10.149399Z

thanks

ericdallo 2025-11-18T16:57:52.759249Z

managed to create a test, the issue is when the .class is inside a jar, the .class alone works ๐Ÿคฏ

borkdude 2025-11-18T16:58:12.973229Z

Hmmhmhm

ericdallo 2025-11-18T16:58:36.986489Z

will now debug it

ericdallo 2025-11-18T17:03:47.212619Z

well, I don't know all the consequences of removing that :)

borkdude 2025-11-18T17:04:15.415959Z

I think that was added to prevent analyzing all kinds of generated classes from clojure core AOT

ericdallo 2025-11-18T17:04:29.306069Z

yeah, I imaged that

borkdude 2025-11-18T17:05:09.208929Z

-rw-r--r--  2.0 unx     2251 b- defN 25-Jun-02 14:10 clojure/core$memfn.class
etc

borkdude 2025-11-18T17:05:15.669089Z

-rw-r--r--  2.0 unx     1031 b- defN 25-Jun-02 14:10 clojure/uuid$fn__8546.class

borkdude 2025-11-18T17:05:17.881319Z

etc

borkdude 2025-11-18T17:05:32.733039Z

perhaps we can just ignore clojure/ + $

ericdallo 2025-11-18T17:05:39.719449Z

I guess

borkdude 2025-11-18T17:05:43.640219Z

but other AOT-ed clojure libs will have similar junk

ericdallo 2025-11-18T17:05:52.533329Z

yeah, kind hard

ericdallo 2025-11-18T17:06:11.659989Z

would be nice if we could somehow distinguish clojure generated $ classes than java ones

borkdude 2025-11-18T17:06:18.161489Z

dollar + all lower case name (barring munging) would do it I guess

borkdude 2025-11-18T17:06:36.578629Z

-rw-r--r--  2.0 unx     1216 b- defN 25-Jun-02 14:10 clojure/core$reduced_QMARK___inliner__5990.class

borkdude 2025-11-18T17:06:50.652799Z

I mean _QMARK_

ericdallo 2025-11-18T17:06:56.173339Z

yeah

borkdude 2025-11-18T17:07:50.057419Z

or maybe simpler: $ followed by a lowercase character

borkdude 2025-11-18T17:07:52.967479Z

seems a safe heuristic

ericdallo 2025-11-18T17:08:30.999629Z

Seems better yeah

borkdude 2025-11-18T17:12:08.610279Z

we would miss classes generated from deftype/protocols etc I think, but those are relatively rare

ericdallo 2025-11-18T17:13:23.432209Z

but defrecords classes would keep yet right?

borkdude 2025-11-18T17:13:32.464179Z

yeah

ericdallo 2025-11-18T17:13:40.981329Z

sounds acceptable

borkdude 2025-11-18T17:15:04.807799Z

we can check the difference by loading bb extract:java-members

borkdude 2025-11-18T17:15:12.353949Z

and see how many files are added

borkdude 2025-11-18T17:16:08.217499Z

or run lsp on clojure (which it does at startup) and see how much extra garbage that yields)

ericdallo 2025-11-18T17:17:16.658149Z

Ok! does that looks good?

(or (not (str/includes? nm "$"))
    (not (Character/isLowerCase (nth nm (inc (.indexOf nm "$"))))))

ericdallo 2025-11-18T17:26:08.221029Z

It works with clojure-lsp!

ericdallo 2025-11-18T17:26:27.478249Z

ah spoke too soon

ericdallo 2025-11-18T17:27:19.626489Z

I think the issue now is the decompilation with Cfr on lsp side ๐Ÿซ 

borkdude 2025-11-18T17:32:07.305709Z

yeah you need to decompile the outer class

ericdallo 2025-11-18T17:53:20.332729Z

Ok, I think it's working, will push to clj-kondo and do more tests with lsp

ericdallo 2025-11-18T17:57:09.827449Z

reviewplease https://github.com/clj-kondo/clj-kondo/pull/2658

borkdude 2025-11-18T18:41:45.959999Z

1 windows test seems to be failing:

FAIL in (local-classes-test) (java_test.clj:88)
expected: (match? (m/in-any-order [{:class "foo.bar.AwesomeClass", :uri #"file:.*/corpus/java/classes/foo/bar/AwesomeClass.class", :filename #".*corpus/java/classes/foo/bar/AwesomeClass.class"} {:class "foo.bar.AwesomeClass$Foo", :uri #"file:.*/corpus/java/classes/foo/bar/AwesomeClass\$Foo.class", :filename #".*corpus/java/classes/foo/bar/AwesomeClass\$Foo.class"}]) awesome-class-defs)
  actual: ({:class "foo.bar.AwesomeClass$Foo",
  :uri
  "file:/D:/a/clj-kondo/clj-kondo/corpus/java/classes/foo/bar/AwesomeClass$Foo.class",
  :filename
  (mismatch
   (expected
    #".*corpus/java/classes/foo/bar/AwesomeClass\$Foo.class")
   (actual
    "D:\\a\\clj-kondo\\clj-kondo\\corpus\\java\\classes\\foo\\bar\\AwesomeClass$Foo.class")),
  :flags #{}}
 {:class "foo.bar.AwesomeClass",
  :uri
  "file:/D:/a/clj-kondo/clj-kondo/corpus/java/classes/foo/bar/AwesomeClass.class",
  :filename
  (mismatch
   (expected
    #".*corpus/java/classes/foo/bar/AwesomeClass.class")
   (actual
    "D:\\a\\clj-kondo\\clj-kondo\\corpus\\java\\classes\\foo\\bar\\AwesomeClass.class")),
  :flags #{:public}})

ericdallo 2025-11-18T18:47:28.899029Z

Yeah, I will just check for the class existence

ericdallo 2025-11-18T18:47:50.209909Z

something to improve in clj-kondo assert-submaps2 in the future is support use something like m/in-any-order from matcher-combinators

ericdallo 2025-11-18T18:47:58.050429Z

for now, it should work my last push

ericdallo 2025-11-18T19:00:01.105099Z

Not sure why one check is failing, doesn't related to the PR

ericdallo 2025-11-18T21:20:07.040189Z

@borkdude is anything missing from me https://github.com/clj-kondo/clj-kondo/pull/2658?

borkdude 2025-11-18T21:20:34.303169Z

let me look at the code

borkdude 2025-11-18T21:20:54.140249Z

some questions. why was corpus/java/sources/foo/bar/AwesomeClass.java changed?

ericdallo 2025-11-18T21:21:08.086039Z

because its code was wrong

ericdallo 2025-11-18T21:21:19.606149Z

there was a method with a class inside it

ericdallo 2025-11-18T21:21:26.746059Z

I don't know how that passed before

borkdude 2025-11-18T21:25:24.330839Z

you tried to compile it? ok

borkdude 2025-11-18T21:25:46.302219Z

I see it now, that's weird indeed

ericdallo 2025-11-18T21:27:03.404459Z

yeah, it works with clojure-lsp, fixes the issue on clojure-lsp side

borkdude 2025-11-18T21:27:23.179929Z

my suggestion here would be:

(or (not (str/includes? nm "$"))
                                                 (not (Character/isLowerCase ^Character (nth nm (inc (.indexOf nm "$"))))))
First take the index of "$". If it's negative, we're good. If it's positive, use .charAt to take the next character and check for lowercase. You should then also check if you're not beyond the length of the string for out of bounds exception or whatnot.

borkdude 2025-11-18T21:27:52.628229Z

I mean, charAt will crash if you go beyond the length

borkdude 2025-11-18T21:29:13.343669Z

actually nth will do that for you if you provide a not-found value, so let's do that

ericdallo 2025-11-18T21:29:55.949279Z

got it, what default-value?

ericdallo 2025-11-18T21:30:02.128619Z

not-found*

ericdallo 2025-11-18T21:30:39.632719Z

it could be any char

borkdude 2025-11-18T21:31:12.363059Z

something like this?

(when-let [idx (str/index-of ...)]
  (not (Character/isLowerCase ^Character (nth nm (inc idx) \A)))
It's a bit ugly
(when-let [idx (str/index-of ...)]
  (when-let [^Character c (nth nm (inc idx) nil)
    (not (Character/isLowerCase c))

ericdallo 2025-11-18T21:31:47.140719Z

then when-let is cleaner

borkdude 2025-11-18T21:31:57.958779Z

oh wait, it should return true when it doesn't include $ so you should also do that

ericdallo 2025-11-18T21:33:25.468759Z

(or (not (str/includes? nm "$"))
                                                 (when-let [idx (str/index-of nm "$")]
                                                   (when-let [^Character c (nth nm (inc idx) nil)]
                                                     (not (Character/isLowerCase c)))))
?

borkdude 2025-11-18T21:34:34.555969Z

(not (some-> (str/index-of ...)
             inc
             (->> (nth nm nil))
             Character/isLowerCase))
hehe almost, the thread isn't right in nth

ericdallo 2025-11-18T21:34:50.243959Z

or we can get rid of the firs when-let because the or already checks that

ericdallo 2025-11-18T21:35:10.566309Z

(or (not (str/includes? nm "$"))
                                                 (when-let [^Character c (nth nm (inc (str/index-of nm "$")) nil)]
                                                   (not (Character/isLowerCase c))))

borkdude 2025-11-18T21:36:21.848489Z

(let [idx (str/index-of nm "$")]
  (or (not idx)
    (when-let [^Character c (nth nm (inc idx) nil)]
      (not ...))

borkdude 2025-11-18T21:36:25.128459Z

I think I'd prefer that

ericdallo 2025-11-18T21:38:15.273459Z

pushed!

borkdude 2025-11-18T21:39:58.658399Z

thanks so much. the only thing left checking is how much more garbage we get in the class definition/usage stuff in .clj-kondo/.cache

ericdallo 2025-11-18T21:40:16.090769Z

ah yeah, need to check that

borkdude 2025-11-18T21:40:24.350589Z

i.e. if our filter for clojure classes is good enough

ericdallo 2025-11-18T21:41:05.789289Z

I think the bb idea was the best

borkdude 2025-11-18T21:41:16.993859Z

bb idea?

ericdallo 2025-11-18T21:41:31.991979Z

bb extract:java-members

borkdude 2025-11-18T21:41:38.274089Z

๐Ÿ‘

ericdallo 2025-11-18T21:41:56.704699Z

Iแธฟ getting this tho:

Execution error (NoSuchFileException) at sun.nio.fs.UnixException/translateToIOException (UnixException.java:92).
/tmp/java-cache/v1/java

Full report at:
/tmp/clojure-1439160252713424056.edn
Error while executing task: extract:java-members

borkdude 2025-11-18T21:42:13.223959Z

let me take alook

borkdude 2025-11-18T21:42:45.942939Z

oh I'm not getting it. do you have a tmp dir?

borkdude 2025-11-18T21:43:07.486569Z

I can change that if it's a nixos thing

borkdude 2025-11-18T21:43:30.202149Z

maybe paste the output of /tmp/clojure-1439160252713424056.edn in a gist

borkdude 2025-11-18T21:46:28.976879Z

it just works over here. I'll be afk for a brief moment, but will be back

ericdallo 2025-11-18T21:48:53.712699Z

I'm bee afk too, feel free to check that if you can, otherwise I can take a look tomorrow, I believe this check would be better if done in your side because of this nix issue ๐Ÿ™

borkdude 2025-11-18T21:49:16.630179Z

oh ok, yeah that makes sense

borkdude 2025-11-20T16:33:05.529969Z

@ericdallo I'm inspecting classes like this:

clj -M:clj-kondo/dev --lint "$(clojure -Spath)" --config '{:output {:format :edn} :analysis {:java-class-definitions true :java-class-usages true}}' > /tmp/out.edn

cat /tmp/out.edn | jet --from edn -t ':analysis :java-class-definitions' > /tmp/class.edn
In class.edn I find classes like:
"com.github.javaparser.GeneratedJavaParser$1"
com.github.javaparser.ParserConfiguration$1
also:
clojure.core$_LT__EQ___inliner__5641
clojure.core$Throwable__GT_map$fn__7563
clojure.lang.Util$3
clojure.core$_PLUS__SINGLEQUOTE_
I'll paste the class.edn file here so we can filter out all clojure.* names to inspect them more. But it seems as a rule of thumb: We can also ignore โ€ข inner classes starting with numbers โ€ข underscores (result from munging, probably not interesting for java interop?) โ€ข containing the string __inliner__ Perhaps some more

borkdude 2025-11-20T16:33:35.413229Z

you don't need the bb task for this, that honestly only analyzed source code so it didn't catch anything interesting for the ASM filter

ericdallo 2025-11-20T16:34:55.178389Z

I see, sounds good

borkdude 2025-11-20T16:50:18.487269Z

I can make a commit (since you pushed in a branch of the kondo repo anyway)

ericdallo 2025-11-20T16:53:34.871359Z

please!

borkdude 2025-11-20T17:05:56.277309Z

pushed. I think I got most of the junk now. can you review also the changed files to see if there's not any junk in there?

borkdude 2025-11-20T17:06:01.984559Z

then I'll merge if CI passes

ericdallo 2025-11-20T17:06:20.009809Z

let me check

ericdallo 2025-11-20T17:07:22.563679Z

a lot of cache files were changed, was that expected?

ericdallo 2025-11-20T17:08:17.221319Z

besides that, looks good

borkdude 2025-11-20T17:29:20.092449Z

yes, a lot of Foo.Bar were changed in Foo$Bar ;)

๐Ÿ˜… 1
borkdude 2025-11-20T19:17:01.708909Z

merged

ericdallo 2025-11-20T20:29:09.201419Z

Done in clojure-lsp!

ericdallo 2025-11-20T20:29:24.679779Z

the localtions are probably something we wanna improve next in clj-kondo, especially now with inner classes

borkdude 2025-11-20T20:41:41.956799Z

awesome, confirming it works barring location.

borkdude 2025-11-20T20:44:34.311269Z

but this is already great!

ericdallo 2025-11-20T20:44:57.994389Z

nice!

rafaeldelboni 2025-11-18T20:33:48.675579Z

Is there a way to make clojure-lsp think that a squint project is a cljs project? Because I'm having a problem when trying to look at the clojure.core fns documentation in my editor (things like defn for example) it doesn't show anything, but in a normal cljs project it works correcly. But in the same project I can see docstrings and all other features of lsp, only things related to clojure.core stuff doesn't work for me. In the printscreen you can see: โ€ข Normal cljs project documentation over defn, working โ€ข Squint project documentation over defn, not working โ€ข Squint project documentation of a local defined function, working Repro: https://github.com/rafaeldelboni/squint-vite-react Version:

clojure-lsp --version
clojure-lsp 2025.08.25-14.21.46
clj-kondo 2025.07.28

ericdallo 2025-11-18T20:35:07.232869Z

Interesting, Clojure-lsp guess that by the extension, is there any repro I can try? I never tried squint before

rafaeldelboni 2025-11-18T20:36:18.669919Z

Yes https://github.com/rafaeldelboni/squint-vite-react

ericdallo 2025-11-18T20:50:45.175769Z

thanks, will try it later tonight

โค๏ธ 1
borkdude 2025-11-18T20:51:49.224229Z

a workaround to this problem is probably to add a deps.edn with :paths ["src"]

borkdude 2025-11-18T20:51:58.340139Z

just to fool clojure-lsp into thinking it belongs to the classpath

borkdude 2025-11-18T20:52:31.265389Z

but would be nice if clojure-lsp recognized squint.edn as a deps file too

ericdallo 2025-11-18T20:53:24.525009Z

that's easy to recognize, @borkdude is there any classpath string command using squint? like bb print-deps --format classpath

borkdude 2025-11-18T20:54:11.970169Z

no, but you can just treat it like a deps.edn for now

borkdude 2025-11-18T20:54:25.282299Z

the only relevant part is :paths

ericdallo 2025-11-18T21:12:55.079309Z

yeah, same issue we had with bb, there is no easy way to simulate the classpath unless we have a one-line clojure command that returns a classpath string

borkdude 2025-11-18T21:14:07.380509Z

deps.clj supports -Sdeps-file squint.edn

borkdude 2025-11-18T21:14:33.327519Z

maybe the official clojure CLI does now too, let me check

borkdude 2025-11-18T21:17:32.629489Z

yep:

-Sdeps EDN     Deps data or file to use as the last deps file to be merged

borkdude 2025-11-18T21:17:38.139909Z

so you can just use that for squint

ericdallo 2025-11-18T21:18:05.200229Z

nice, will try

ericdallo 2025-11-19T01:12:46.666969Z

@borkdude this won't work for this case, since clojurescript is not available, so cljs.core/defn analysis don't exist. I believe the best here is have a npx squint classpath command or something, that would make clojure-lsp easier as well

ericdallo 2025-11-19T01:13:51.912019Z

otherwise we would need to read and get path of squint.edn , use the path to pass to clj -Sdeps '{:paths [...]}' and include the clojurescript lib with a hardcoded version, seems too many workarounds to live in clojure-lsp

borkdude 2025-11-19T09:17:20.221429Z

eh no... like I said, you can now use clj -Sdeps squint.edn

borkdude 2025-11-19T09:17:49.732929Z

and why include clojurescript? you don't need it for defn, clj-kondo has built-in stuff for defn etc.

borkdude 2025-11-19T09:19:03.259989Z

oh it's about docstrings, then yeah. Maybe the user can then just use a deps.edn with a :dev alias with clojurescript and the squint path in it. I'm not going to add a premature classpath thing to squint, that just doesn't make sense, especially not since it's not really CLJS

ericdallo 2025-11-19T12:08:42.257749Z

not only docstrings, but analysis which affect more features than only docstrings I believe any build tool related to clojure should have a way to get a classpath, for now I'm trying clj -Sdeps squint.edn -Spath , so user need to include clojurescript dep in squint.edn in a dev alias right?

ericdallo 2025-11-19T12:08:50.418219Z

@rafaeldelboni is that enough for you?

rafaeldelboni 2025-11-19T12:09:38.183489Z

Sounds ok to me, yes

ericdallo 2025-11-19T12:09:53.326879Z

I think that reduces the "Just works" behavior, as all new squint user would need to configure that to have a working IDE, but sounds like a good start

rafaeldelboni 2025-11-19T12:10:59.875099Z

After this is done, worth adding a note about lsp support on squint readme, wdyt borkdude?

borkdude 2025-11-19T12:17:17.594629Z

Squint edn doesnt support a dev alias but since its ignored its fine to add it. Wouldnโ€™t it make sense to just add built in default analysis for some libs though? Nbb probably has the same issue with CLJS. Clj-kondo has built in support for .cljs and .clj files by just including some default libraries in its bundled analysis including the newest clojure and ClojureScript

borkdude 2025-11-19T12:19:05.253879Z

Clojure dart users or any other new dialect would also benefit from that

rafaeldelboni 2025-11-19T12:21:13.909449Z

Since lsp syncs with clojuredocs, wouldn't be the case for those cases (squint, nbb, cljdart) to just show data from there?

ericdallo 2025-11-19T12:21:38.690059Z

the problem is not docstrings/clojuredocs, but analysis

ericdallo 2025-11-19T12:21:58.128869Z

find definition won t work for example without fixing this issue

ericdallo 2025-11-19T12:22:52.413759Z

@borkdude I think we can fix especifically for clojure and clojurescript, but still sounds like a adhoc solution, especially what version to use, missing functions, or any extra lib that may exist (like cljd lib itself)

borkdude 2025-11-19T12:23:00.823369Z

well find definition would not be a reason to add CLJS to squint deps, CLJS defn isnt squint defn

borkdude 2025-11-19T12:23:12.827789Z

So that would be a bogus find definition

ericdallo 2025-11-19T12:24:10.519989Z

yeah I don't know what squint does, but the point is that I think the build tool should tell what lib is using, not LSP

ericdallo 2025-11-19T12:24:31.927739Z

like bb having lots of built-in libs and stuff that are printed via bb print-deps --format classpath and that works great now

borkdude 2025-11-19T12:27:13.902679Z

Yes, for bb it makes sense. For squint, not so much,except that you can treat squint.edn (and nbb.edn) as deps.edn. Similar for Clojure CLR btw

borkdude 2025-11-19T12:33:28.292089Z

Iโ€™ll figure something out to add to the README without changing either Clojure-LSP and squint, itโ€™s doable

ericdallo 2025-11-19T12:35:52.231869Z

yeah I can see the difference, it's something to think a little bit more indeed

borkdude 2025-11-19T15:56:17.858589Z

@rafaeldelboni can you try this (and perhaps Eric can double-check if I'm suggesting the right thing):

{:project-specs [{:project-path "squint.edn"
                  :classpath-cmd ["clojure" "-Spath" "-A:lsp"]}]}
and then in squint.edn:
{:paths ["src"]
 :aliases {:lsp {:extra-deps {org.clojure.clojurescript {:mvn/version "..."
I don't know what project path is for. Perhaps just this also works:
{:project-specs [{:classpath-cmd ["clojure" "-Spath" "-Sdeps" "squint.edn" "-A:lsp"]}]}
Note that the order of -Sdeps and -A:... is wrong in the original lsp docs. According to the clojure CLI -S stuff goes first. Sometimes it doesn't matter but sometimes it does, so better do it the official way

ericdallo 2025-11-19T15:57:13.878039Z

project-path is what will trigger that command, clojure-lsp will only trigger if that file is found

ericdallo 2025-11-19T15:57:35.458159Z

yeah, for a temporary solution that should work

rafaeldelboni 2025-11-19T15:58:18.589629Z

Where do I add the project-specs config? .lsp/config.edn?

borkdude 2025-11-19T15:58:24.637229Z

yes

borkdude 2025-11-19T15:58:47.969999Z

ok so in both cases you do need to add the -Sdeps squint.edn argument as well

rafaeldelboni 2025-11-19T16:26:45.924809Z

it worked for me with a mix of both

{:project-specs [{:project-path "squint.edn"
                  :classpath-cmd ["clojure" "-Spath" "-Sdeps" "squint.edn" "-A:lsp"]}]}

rafaeldelboni 2025-11-19T16:27:03.580899Z

I can't declares a project-specs without a project-path

rafaeldelboni 2025-11-19T16:27:29.843319Z

and the other classpath wasn't getting the clojurescript into the paths

borkdude 2025-11-19T16:27:35.342489Z

yeah I guess that's expected

borkdude 2025-11-19T16:27:45.786989Z

the other classpath?

rafaeldelboni 2025-11-19T16:27:51.972289Z

{:project-specs [{:project-path "squint.edn"
                  :classpath-cmd ["clojure" "-Spath" "-A:lsp"]}]}

rafaeldelboni 2025-11-19T16:27:55.562759Z

this example

borkdude 2025-11-19T16:28:07.367309Z

yes, I told later: you need -Sdeps squint.edn for both examples

rafaeldelboni 2025-11-19T16:28:11.573379Z

ah ok

rafaeldelboni 2025-11-19T16:28:23.763209Z

yeah but it works I will update the repro repo

borkdude 2025-11-19T16:28:40.834149Z

cool! maybe you can make a PR to squint's README where we mention this for LSP users

borkdude 2025-11-19T16:28:55.442519Z

actually this would work for nbb users as well

ericdallo 2025-11-19T16:29:16.766199Z

is the lsp alias required? can't be dev? it's the standard lsp uses for all other project types

ericdallo 2025-11-19T16:29:34.039829Z

so with that we could have that on lsp, and user would just need to declare clojurescript in that profile

borkdude 2025-11-19T16:29:42.900339Z

it can be dev but this would suggest that clojurescript is needed for squint development, which isn't true

ericdallo 2025-11-19T16:30:09.610129Z

tooling is development ๐Ÿ˜›

borkdude 2025-11-19T16:30:17.031369Z

fair enough

borkdude 2025-11-19T16:31:08.402809Z

I'll let @ericdallo suggest the simpler one with the dev alias. Since you still need the classpath-cmd, I don't see how that would be much simpler though

borkdude 2025-11-19T16:31:24.916659Z

just {:project-paths "squint.edn"} doesn't work

ericdallo 2025-11-19T16:32:01.398069Z

yeah, I can add to clojure-lsp this project-path + classpath cmd to run the default aliases like done for other tooling, so users would just need to have that alias with dev profile, with clojurescript in there

ericdallo 2025-11-19T16:32:05.754809Z

sounds good enough for now

๐Ÿ‘ 1
ericdallo 2025-11-19T16:33:55.087789Z

@rafaeldelboni would you mind create a clojure-lsp issue for that please? to include squint.edn as a project-spec

๐Ÿ‘ 1
๐ŸŽ‰ 1
rafaeldelboni 2025-11-19T16:40:49.325229Z

https://github.com/clojure-lsp/clojure-lsp/issues/2158

ericdallo 2025-11-19T16:44:29.935199Z

Done! available soon in #clojure-lsp-builds, I should release clojure-lsp soon too

rafaeldelboni 2025-11-19T16:45:16.272159Z

out of curiosity my version is stuck long time on clojure-lsp 2025.08.25-14.21.46

rafaeldelboni 2025-11-19T16:45:21.742029Z

in brew and archlinux

ericdallo 2025-11-19T16:45:26.820249Z

yep, it's the latest

rafaeldelboni 2025-11-19T16:45:27.211829Z

is there something I'm missing?

rafaeldelboni 2025-11-19T16:45:29.792839Z

ah ok

ericdallo 2025-11-19T16:46:57.572439Z

I may do a release after me and borkdude fix https://clojurians.slack.com/archives/CPABC1H61/p1763467383675949

โค๏ธ 2
Harold 2025-11-18T22:09:57.114609Z

I have some elisp code that I run when I'm switching work between different projects (mostly it just closes buffers, and clears some other state), and something about it is triggering this minibuffer prompt:

Server clojure-lsp:267077 exited (check corresponding stderr buffer for details). Do you want to restart it? (y or n) 
The mentioned stderr buffer is also gone at this point. Is there some way to not have this prompt pop up? (I don't think I really care if it 'restarts' or not, I'm happy to have it restart when I later open another project's file, or not, or whatever simple_smile).

ericdallo 2025-11-18T22:12:56.643849Z

the way lsp-mode works is to kill any left lsp servers running if all buffers related to it were kill But good question, never wondered about that, let me check

๐Ÿ™‡ 1
ericdallo 2025-11-18T22:13:59.196769Z

I think:

(setq lsp-restart 'ignore)
or auto-restart

Harold 2025-11-18T22:14:45.295919Z

Thank you, I will try that.

Harold 2025-11-18T22:15:05.571859Z

I appreciate the very quick response.

๐Ÿš€ 1
Harold 2025-11-18T23:11:14.157289Z

That did it! Just switched projects again, and didn't get the prompt. ๐Ÿ‘

๐Ÿ’™ 1