lsp

julienvincent 2026-01-06T11:49:41.763519Z

Hi I am not sure if I am just doing something wrong, but I can't get the output of clojure-lsp format to match a format lsp action from within my editor. I have code which uses :style/indent metadata to inform formatting, and usages of this are formatted correctly when I run format from within my editor (so via a clojure-lsp action) but when I run clojure-lsp format it ignores the :style/indent metadata and indents it using default settings. I am using the same version of clojure-lsp (the latest release). Trying to setup format lint rules in CI for a large project, and this makes it impossible. I can't find any known issues about it, am I doing something wrong or is this a bug? If it's a bug I am surprised I am the first to mention this - doesn't seem like an edge-case usage. Example in thread ⬇️

julienvincent 2026-01-06T11:54:09.622599Z

Very easy to reproduce:

(ns io.julienvincent.definition
  (:refer-clojure :exclude [reify]))

(defn do-thing
  {:style/indent :defn}
  [_varname _varbody])
(ns io.julienvincent.usages
  (:require [io.julienvincent.definition :as d]))

(d/do-thing 1
  2)
The above, formatted using my lsp format action. Running clojure-lsp format in this project root:
❯ clojure-lsp format --dry
[ 99%] Project analyzed            Formatting namespaces...
--- a/src/io/julienvincent/usages.clj
+++ b/src/io/julienvincent/usages.clj
@@ -2,4 +2,4 @@
   (:require [io.julienvincent.definition :as d]))

 (d/do-thing 1
-  2)
+            2)

julienvincent 2026-01-06T11:56:03.029899Z

❯ clojure-lsp --version
clojure-lsp 2025.11.28-12.47.43
clj-kondo 2025.10.24-SNAPSHOT

ericdallo 2026-01-06T12:13:44.598209Z

let me test it

ericdallo 2026-01-06T12:16:57.590959Z

I can repro, but I saw that in the past and I believe there is some trick/reason

ericdallo 2026-01-06T12:27:12.912269Z

both use same piece of code, but the problem seems that in https://github.com/clojure-lsp/clojure-lsp/blob/c2126582f633d78b9fa751028a21e359b6527ce6/lib/src/clojure_lsp/feature/format.clj#L83-L96 when we extract the style/indent it's comming empty for CLI

julienvincent 2026-01-06T12:45:47.635669Z

Hahaha

ericdallo 2026-01-06T12:45:53.039449Z

😅

julienvincent 2026-01-06T12:46:12.485719Z

Well, shit. I guess this could be put behind a flag or something

ericdallo 2026-01-06T12:46:26.857529Z

it took almost 2 years to someone complain :p

ericdallo 2026-01-06T12:46:33.601149Z

I guess

julienvincent 2026-01-06T12:47:59.658879Z

In the meantime I started mapping out all our functions which have this metadata to explicit cljfmt :extra-indent config in the project root. It's pretty sad having to do this, but it's a workable solution for me

ericdallo 2026-01-06T12:48:15.459639Z

yeah that would work

ericdallo 2026-01-06T12:49:32.657399Z

more context about the change https://github.com/clojure-lsp/clojure-lsp/issues/1723

ericdallo 2026-01-06T12:49:41.260849Z

but a flag should be possible, will take a look

ericdallo 2026-01-06T12:58:27.617439Z

the good thing is that I'm going do a change that would make possible use a existing flag that already works for all CLI commands, so would be:

clojure-lsp format --dry --analysis '{:type :project-only}'
the default is project-namespaces-only which doesn't work with style/indent

ericdallo 2026-01-06T13:00:06.107729Z

just pushed @m401, would be nice if you could test as well

julienvincent 2026-01-06T13:04:08.607179Z

Oh cool that's a nice solution. Just out for lunch, will test when I'm back!

ericdallo 2026-01-06T13:19:13.083019Z

sure, fixed your other style/indent issue as well

julienvincent 2026-01-06T14:03:21.433739Z

Can confirm, both issues fixed! Thanks :)

ericdallo 2026-01-06T14:05:41.170639Z

cool thank you!

julienvincent 2026-01-06T16:28:16.832409Z

Ok I did find an issue with the latest fixes. It now looks like I cannot define my own style/indent config for my own custom macros if those macros share names with clojure.core. For example:

(ns io.julienvincent.definition
  (:refer-clojure :exclude [reify]))

(defmacro reify
  {:style/indent :defn}
  [_varname])

(defmacro reify2
  {:style/indent :defn}
  [_varname])

(defmacro reify3
  {:style/indent [1 [1]]}
  [_varname])

(defmacro reify4
  {:style/indent [1 [:defn]]}
  [_varname])

(comment

  (reify 1
    (foo [x]
      1))

  (reify2 1
    (foo [x]
         1))

  (reify3 1
    (foo [x]
      1))

  (reify4 1
    (foo [x]
      1))

  nil)
Notice how reify doesn't format like reify2 but it should

julienvincent 2026-01-06T16:29:11.679609Z

Also, side note, I had no idea I could do things like {:style/indent [1 [1]]}. Is the spec defined somewhere? I couldn't find it

ericdallo 2026-01-06T16:29:35.678899Z

not sure about the spec, but it comes from cljfmt logic

julienvincent 2026-01-06T16:30:11.038319Z

Well, no I don't think it's the same syntax as cljfmt. It is mapped to cljfmt indent syntax by clojure-lsp somehow

ericdallo 2026-01-06T16:30:58.443989Z

sorry, I meant cider, not cljfmt

👍 1
ericdallo 2026-01-06T16:33:07.748899Z

just tested your repro, but it's weird because we are mapping correctly to cljfmt indents:

{:indents {clojure-sample.foo/reify [[:inner 0]], clojure-sample.foo/reify2 [[:inner 0]], clojure-sample.foo/reify3 [[:block 1] [:inner 1]], clojure-sample.foo/reify4 [[:block 1] [:inner 1]], nrepl.misc/returning [[:block 1]]}}

ericdallo 2026-01-06T16:33:34.029829Z

right?

julienvincent 2026-01-06T16:34:19.533059Z

That looks correct to me, yea

julienvincent 2026-01-06T16:34:29.052899Z

maybe :indents doesn't override

ericdallo 2026-01-06T16:34:31.712939Z

hum, maybe a cljfmt bug

ericdallo 2026-01-06T16:34:33.082229Z

yeah

ericdallo 2026-01-06T16:34:42.827179Z

I wonder if it should be extra-indents

julienvincent 2026-01-06T16:34:45.978529Z

I can play with it in a bit - just going into a meeting now

👍 1
julienvincent 2026-01-06T21:38:38.452859Z

Ok, can confirm I think this is a bug in cljfmt. If I use just cljfmt with some indents config it completely ignores reify.

{:extra-indents {io.julienvincent.definition/reify [[:inner 1]]
                 io.julienvincent.definition/reify2 [[:inner 1]]}}
The above, reify is ignored.
{:extra-indents {reify [[:inner 1]]
                 io.julienvincent.definition/reify2 [[:inner 1]]}}
however overriding the definition for un-namespaced reify does apply (to everything)

ericdallo 2026-01-06T22:03:27.475629Z

yeah, maybe @weavejester can help here

weavejester 2026-01-06T22:58:28.568629Z

The more specific namespaced reify probably should override the unnamespaced one. Feel free to open an issue.

2
weavejester 2026-01-06T22:59:03.134159Z

cljfmt also doesn't currently support looking for metadata, but it is functionality that's planned.

julienvincent 2026-01-07T11:05:17.756699Z

Surprisingly, this issue seems only to happen with reify (well, maybe others too?). I was playing with defrecord and it doesn't get overwritten - so I can attach definition specific indents - just not to reify. Weird! I'll open an issue in a bit