Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent indentation for macros #3490

Closed
rrudakov opened this issue Sep 29, 2023 · 14 comments
Closed

Inconsistent indentation for macros #3490

rrudakov opened this issue Sep 29, 2023 · 14 comments

Comments

@rrudakov
Copy link
Contributor

Expected behavior

  1. Macros indentation is consistent with cljfmt
  2. Indentation is should be consistent when M-x cider-format-buffer is called.

Actual behavior

Indentation is inconsistent (see screenshots)

Steps to reproduce the problem

  1. Create a simple project:
  • deps.edn content:
{:paths ["src"]
 :deps  {tortue/spy {:mvn/version "2.13.0"}}}
  • src/com/example/app.clj content:
(ns com.example.app
  (:require
   [clojure.test :refer [deftest]]
   [spy.assert :as assert]
   [spy.core :as spy]
   [spy.test]))

(defn- foo
  [bar]
  (println bar))

(deftest dummy-test
  (with-redefs [foo (spy/spy foo)]
    (foo 123)
    (assert/called-once-with? foo
                              123)))
  1. Call M-x cider-jack-in
  2. Place cursor on the last line (before 123) and press TAB (indent-for-tab-command). 123 will be indented as "body" (with 2 spaces indentation relative to the previous line)
  3. Execute M-x cider-format-buffer. 123 will be aligned vertically with foo (as function arguments)
image

If I place foo to the new line the indentation is even more weird:

image

I assume it's related to indentation inference? In stable CIDER 1.8 the indentation is correct:

image image

Environment & Version information

CIDER version information

;; CIDER 1.8.0-snapshot (package: 20230929.455), nREPL 1.0.0
;; Clojure 1.11.1, Java 17.0.8.1

Lein / Clojure CLI version

Clojure CLI 1.11.1

Emacs version

GNU Emacs 29.1.50 (build 1, aarch64-apple-darwin23.0.0, NS appkit-2487.00 Version 14.0 (Build 23A344)) of 2023-09-28

Operating system

MacOS 14

JDK distribution

openjdk version "17.0.8.1" 2023-08-24
OpenJDK Runtime Environment Homebrew (build 17.0.8.1+0)
OpenJDK 64-Bit Server VM Homebrew (build 17.0.8.1+0, mixed mode, sharing)
@vemv
Copy link
Member

vemv commented Sep 29, 2023

Thanks for the detailed report!

Checking out https://github.com/alexanderjamesking/spy/blob/e27887b3a0a9c9e5078e773b92b84c7571ce59a5/src/clj/spy/assert.clj, I'd say that the issue is that (defmacro called-once-with? [f & args] is expected to be indented like a function, despite being implemented as a macro.

There was a similar case asked about here: https://clojurians.slack.com/archives/C0617A8PQ/p1695695401220199?thread_ts=1695694483.271689&cid=C0617A8PQ

The solution is to add :style/indent metadata. It actually always has been best practice to add it, instead of letting an arbitrary behavior set in.

So I'd recommend a PR against that repo.

You can iteratively try out indentation styles using (alter-meta! #'spy.assert/called-once-with? assoc :style/indent ,,,). Such modifications are good to leave in e.g. user.clj while the PR is open.

Cheers - V

@vemv vemv closed this as completed Sep 29, 2023
@rrudakov
Copy link
Contributor Author

Thank you for quick response @vemv!

Maybe it would be a good idea to introduce some defcustom to disable automatic indentation reference and prefer the old behaviour (at least compatibility with cljmft still seems broken in the current state)?

@dakra
Copy link

dakra commented Sep 29, 2023

I had a similar problems a few times already (e.g. promesa threading macros).
I think a defcustom that you can set in Emacs to overwrite or add :style/indent for a specific macro would be a good idea.
Obviously adding it upstream to the lib is preferred but sometimes you can't or don't want to.

@vemv
Copy link
Member

vemv commented Sep 29, 2023

Without inference, a lot of other macros will look non-idiomatic.

CIDER has always fostered :style/indent. Throughout the years I've had to manually add it many times for things to look as envisioned in clojure-mode, the clojure style guide, etc.

I believe inference forces users to be more aware of https://docs.cider.mx/cider/indent_spec.html and to add it from time to time. That's a good thing.

CIDER's job is not only to be compatible with cljfmt "no matter how", but for your Clojure code to look actually more accurate/informative.

The best we could do, probably, is to add a whiltelist for macros that shouldn't be infered. But then again, if you are configuring that, you could as well be configuring :style/indent as a PR or locally under user.clj (or any file that will be loaded, really).

@vemv
Copy link
Member

vemv commented Sep 29, 2023

Another approach that could alleviate this as a "side-effect" is supporting .cljfmt.edn files (clojure-emacs/cider-nrepl#754)

I intend to get back at that PR after we release CIDER 1.8.0.

@bbatsov
Copy link
Member

bbatsov commented Sep 29, 2023

@vemv Perhaps short-term you can just expand the docs to feature something in "Troubleshooting" or the indentation section, so it's easier for to find the information they are looking for.

@dakra
Copy link

dakra commented Sep 29, 2023

I guess this is a different issue but reading https://docs.cider.mx/cider/indent_spec.html#indentation-inference
I think promesa.core/-> should be treated after inference as clojure.core/-> (same name, same args).

I can create a new issue for it if you think this is a bug. Otherwise I'll make a PR to promesa adding :style/indent.

@vemv
Copy link
Member

vemv commented Sep 29, 2023

Thanks! I'll check it out today

@vemv
Copy link
Member

vemv commented Sep 29, 2023

I've fixed that (if you are curious: clojure-emacs/orchard@13c3ea7) and will let you know when cider-nrepl is bumped - should happen during this weekend.

@dakra
Copy link

dakra commented Sep 29, 2023

🎉 Awesome, thanks.

@vemv
Copy link
Member

vemv commented Oct 5, 2023

cider-nrepl 0.39.0 has been released with those changes.

It's injected by CIDER latest (Git master, or the MELPA snapshot that will be visible within a couple hours)

@vemv
Copy link
Member

vemv commented Oct 15, 2023

I've released cider-nrepl 0.40.0 / cider 1.18.2 with a further fix.

It's not directly related to indentation inference, however it fixes certain indentation cases for clojurescript.

@DerGuteMoritz
Copy link
Contributor

I've released cider-nrepl 0.40.0 / cider 1.18.2 with a further fix.

I am (still?) seeing unexpected indentation with Promesa's threading macros here (i.e. the first form is treated as a "head") using ClojureScript. You mention CIDER 1.18.2 which I assume is a typo - judging from the date you posted the comment, you probably meant 1.8.2. In any case, there appears to be a regression...

@vemv
Copy link
Member

vemv commented May 13, 2024

Please create a separate issue in detail

Thanks - V

@clojure-emacs clojure-emacs locked as resolved and limited conversation to collaborators May 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants