From 606380b3d049ba74ce472ed686aa5a3ff0163bbd Mon Sep 17 00:00:00 2001 From: Cam Saul Date: Tue, 20 Aug 2024 22:54:51 +0000 Subject: [PATCH] Fix indentation for symbols in reader conditionals --- cljfmt/src/cljfmt/core.cljc | 14 ++++++++++- cljfmt/test/cljfmt/core_test.cljc | 42 ++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cljfmt/src/cljfmt/core.cljc b/cljfmt/src/cljfmt/core.cljc index 1e9f0e8..e397a62 100644 --- a/cljfmt/src/cljfmt/core.cljc +++ b/cljfmt/src/cljfmt/core.cljc @@ -248,8 +248,20 @@ (defn- reader-conditional? [zloc] (and (reader-macro? zloc) (#{"?" "?@"} (-> zloc z/down token-value str)))) +(defn- find-next-keyword [zloc] + (z/find zloc z/right #(n/keyword-node? (z/node %)))) + +(defn- first-symbol-in-reader-conditional [zloc] + (when (reader-conditional? zloc) + (when-let [key-loc (-> zloc z/down z/right z/down find-next-keyword)] + (when-let [value-loc (-> key-loc z/next skip-meta)] + (when (token? value-loc) + (z/sexpr value-loc)))))) + (defn- form-symbol [zloc] - (-> zloc z/leftmost token-value)) + (let [zloc (z/leftmost zloc)] + (or (token-value zloc) + (first-symbol-in-reader-conditional zloc)))) (defn- index-matches-top-argument? [zloc depth idx] (and (> depth 0) diff --git a/cljfmt/test/cljfmt/core_test.cljc b/cljfmt/test/cljfmt/core_test.cljc index 7721d1e..639c831 100644 --- a/cljfmt/test/cljfmt/core_test.cljc +++ b/cljfmt/test/cljfmt/core_test.cljc @@ -685,7 +685,47 @@ ":cljs bar)"] ["#?@(:clj foo" " :cljs bar)"]) - "splicing syntax")) + "splicing syntax") + (testing "symbols using reader conditionals should indent correctly" + (let [opts {:indents '{defprotocol [[:block 1] [:inner 1]] + potemkin/defprotocol+ [[:block 1] [:inner 1]]}}] + (testing "standard syntax" + (is (reformats-to? + ["(#?(:clj potemkin/defprotocol+ :cljs defprotocol) MyProtocol" + " \"This is a docstring for my protocol.\"" + " (method [this x]" + " \"This is a docstring for a protocol method.\")" + ")"] + ["(#?(:clj potemkin/defprotocol+ :cljs defprotocol) MyProtocol" + " \"This is a docstring for my protocol.\"" + " (method [this x]" + " \"This is a docstring for a protocol method.\"))"] + opts) + ":clj and :cljs")) + (is (reformats-to? + ["(#?(:clj potemkin/defprotocol+) MyProtocol" + " \"This is a docstring for my protocol.\"" + " (method [this x]" + " \"This is a docstring for a protocol method.\")" + ")"] + ["(#?(:clj potemkin/defprotocol+) MyProtocol" + " \"This is a docstring for my protocol.\"" + " (method [this x]" + " \"This is a docstring for a protocol method.\"))"] + opts) + "only :clj") + (is (reformats-to? + ["(#?(:cljs ^:wow defprotocol) MyProtocol" + " \"This is a docstring for my protocol.\"" + " (method [this x]" + " \"This is a docstring for a protocol method.\")" + ")"] + ["(#?(:cljs ^:wow defprotocol) MyProtocol" + " \"This is a docstring for my protocol.\"" + " (method [this x]" + " \"This is a docstring for a protocol method.\"))"] + opts) + "only :cljs; skip metadata in front of symbol")))) (testing "namespaced maps" (is (reformats-to?