Skip to content

Commit b74f90d

Browse files
authored
Merge pull request #23 from rads/issue-20-2
Fix "Configuration files for `cljfmt` are ignored" (tests passing)
2 parents da980a9 + c3643d7 commit b74f90d

File tree

9 files changed

+99
-32
lines changed

9 files changed

+99
-32
lines changed

src/clojure_mcp/tools/file_edit/pipeline.clj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,14 @@
6262
- Updated context with formatted content for Clojure files, or unchanged for other file types"
6363
[ctx]
6464
(let [file-path (::form-pipeline/file-path ctx)
65-
output-source (::form-pipeline/output-source ctx)]
65+
output-source (::form-pipeline/output-source ctx)
66+
nrepl-client-map @(::form-pipeline/nrepl-client-atom ctx)
67+
formatting-options (form-edit-core/project-formatting-options nrepl-client-map)]
6668
(if (and (file-write-core/is-clojure-file? file-path) output-source)
6769
(try
68-
(let [formatted-source (form-edit-core/format-source-string output-source)]
70+
(let [formatted-source (form-edit-core/format-source-string
71+
output-source
72+
formatting-options)]
6973
(assoc ctx ::form-pipeline/output-source formatted-source))
7074
(catch Exception e
7175
ctx))

src/clojure_mcp/tools/file_write/core.clj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@
2929
3030
Returns:
3131
- A map with :error, :type, :file-path, and :diff keys"
32-
[file-path content]
32+
[nrepl-client-atom file-path content]
3333
(let [file (io/file file-path)
3434
file-exists? (.exists file)
3535
old-content (if file-exists? (slurp file) "")
3636

3737
;; Create a context map for the pipeline
38-
initial-ctx {::pipeline/file-path file-path
38+
initial-ctx {::pipeline/nrepl-client-atom nrepl-client-atom
39+
::pipeline/file-path file-path
3940
::pipeline/source old-content
4041
::pipeline/new-source-code content
4142
::pipeline/old-content old-content
@@ -104,7 +105,7 @@
104105
105106
Returns:
106107
- A map with :error, :type, :file-path, and :diff keys"
107-
[file-path content]
108+
[nrepl-client-atom file-path content]
108109
(if (is-clojure-file? file-path)
109-
(write-clojure-file file-path content)
110+
(write-clojure-file nrepl-client-atom file-path content)
110111
(write-text-file file-path content)))

src/clojure_mcp/tools/file_write/tool.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Before using this tool:
8787

8888
(defmethod tool-system/execute-tool :file-write [{:keys [nrepl-client-atom]} inputs]
8989
(let [{:keys [file-path content]} inputs
90-
result (core/write-file file-path content)]
90+
result (core/write-file nrepl-client-atom file-path content)]
9191
;; Update the timestamp if write was successful and we have a client atom
9292
(when (and nrepl-client-atom (not (:error result)))
9393
(file-timestamps/update-file-timestamp-to-current-mtime! nrepl-client-atom file-path))

src/clojure_mcp/tools/form_edit/core.clj

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
[rewrite-clj.node :as n]
99
[rewrite-clj.paredit :as par]
1010
[cljfmt.core :as fmt]
11+
[cljfmt.config :as cljfmt-config]
12+
[clojure-mcp.config :as config]
1113
[clojure.string :as str]
1214
[clojure.java.io :as io]))
1315

@@ -617,26 +619,40 @@
617619

618620
;; Source code formatting
619621

622+
(def default-formatting-options
623+
{:indentation? true
624+
:remove-surrounding-whitespace? true
625+
:remove-trailing-whitespace? true
626+
:insert-missing-whitespace? true
627+
:remove-consecutive-blank-lines? true
628+
:remove-multiple-non-indenting-spaces? true
629+
:split-keypairs-over-multiple-lines? false
630+
:sort-ns-references? false
631+
:function-arguments-indentation :community
632+
:indents fmt/default-indents})
633+
634+
(defn- load-cljfmt-config [nrepl-user-dir]
635+
(let [path (cljfmt-config/find-config-file nrepl-user-dir)]
636+
(->> (some-> path cljfmt-config/read-config)
637+
(merge default-formatting-options)
638+
(cljfmt-config/convert-legacy-keys))))
639+
640+
(defn project-formatting-options [nrepl-client-map]
641+
(let [nrepl-user-dir (config/get-nrepl-user-dir nrepl-client-map)]
642+
(load-cljfmt-config nrepl-user-dir)))
643+
620644
(defn format-source-string
621-
"Formats a source code string using cljfmt with comprehensive formatting options.
645+
"Formats a source code string using cljfmt. Use the project-formatting-options
646+
function to get comprehensive formatting options for the current project.
622647
623648
Arguments:
624649
- source-str: The source code string to format
650+
- formatting-options: Options for cljfmt
625651
626652
Returns:
627653
- The formatted source code string"
628-
[source-str]
629-
(let [formatting-options {:indentation? true
630-
:remove-surrounding-whitespace? true
631-
:remove-trailing-whitespace? true
632-
:insert-missing-whitespace? true
633-
:remove-consecutive-blank-lines? true
634-
:remove-multiple-non-indenting-spaces? true
635-
:split-keypairs-over-multiple-lines? false
636-
:sort-ns-references? false
637-
:function-arguments-indentation :community
638-
:indents fmt/default-indents}]
639-
(fmt/reformat-string source-str formatting-options)))
654+
[source-str formatting-options]
655+
(fmt/reformat-string source-str formatting-options))
640656

641657
;; File operations
642658

src/clojure_mcp/tools/form_edit/pipeline.clj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,9 @@
414414
[ctx]
415415
(try
416416
(let [source (::output-source ctx)
417-
formatted (core/format-source-string source)]
417+
nrepl-client-map @(::nrepl-client-atom ctx)
418+
formatting-options (core/project-formatting-options nrepl-client-map)
419+
formatted (core/format-source-string source formatting-options)]
418420
(assoc ctx ::output-source formatted))
419421
(catch Exception e
420422
;; Instead of failing, use the original source if available

test/clojure_mcp/tools/file_write/core_test.clj

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
(ns clojure-mcp.tools.file-write.core-test
22
(:require
33
[clojure.test :refer [deftest is testing use-fixtures]]
4+
[clojure-mcp.config :as config]
45
[clojure-mcp.tools.file-write.core :as file-write-core]
6+
[clojure-mcp.tools.test-utils :as test-utils]
57
[clojure.java.io :as io]
68
[clojure.string :as str]))
79

@@ -28,6 +30,7 @@
2830
(binding [*test-dir* test-dir
2931
*test-clj-file* test-clj-file
3032
*test-txt-file* test-txt-file]
33+
(config/set-config! test-utils/*nrepl-client-atom* :nrepl-user-dir test-dir)
3134
(try
3235
(f)
3336
(finally
@@ -37,6 +40,7 @@
3740
(.delete file)))
3841
(.delete test-dir))))))
3942

43+
(use-fixtures :once test-utils/test-nrepl-fixture)
4044
(use-fixtures :each create-test-files-fixture)
4145

4246
(deftest is-clojure-file-test
@@ -79,7 +83,10 @@
7983
(testing "Creating a new Clojure file"
8084
(let [new-file (io/file *test-dir* "new-file.clj")
8185
content "(ns new.namespace)\n\n(defn new-function [x]\n (+ x 10))"
82-
result (file-write-core/write-clojure-file (.getPath new-file) content)]
86+
result (file-write-core/write-clojure-file
87+
test-utils/*nrepl-client-atom*
88+
(.getPath new-file)
89+
content)]
8390
(is (not (:error result)))
8491
(is (= "create" (:type result)))
8592
(is (= (.getPath new-file) (:file-path result)))
@@ -90,7 +97,10 @@
9097
(let [path (.getPath *test-clj-file*)
9198
original-content (slurp *test-clj-file*)
9299
new-content "(ns test.namespace)\n\n(defn test-function [x]\n (+ x 10))"
93-
result (file-write-core/write-clojure-file path new-content)]
100+
result (file-write-core/write-clojure-file
101+
test-utils/*nrepl-client-atom*
102+
path
103+
new-content)]
94104
(is (not (:error result)))
95105
(is (= "update" (:type result)))
96106
(is (= path (:file-path result)))
@@ -100,7 +110,10 @@
100110
(testing "Formatting Clojure code during write"
101111
(let [path (.getPath *test-clj-file*)
102112
unformatted-content "(ns test.namespace)( defn poorly-formatted-fn[x]( + x 5) )"
103-
result (file-write-core/write-clojure-file path unformatted-content)]
113+
result (file-write-core/write-clojure-file
114+
test-utils/*nrepl-client-atom*
115+
path
116+
unformatted-content)]
104117
(is (not (:error result)))
105118
(is (= "update" (:type result)))
106119
(is (not (str/includes? (slurp *test-clj-file*) "poorly-formatted-fn[x]")))
@@ -109,7 +122,10 @@
109122
(testing "Auto-repairs missing closing parenthesis"
110123
(let [path (.getPath *test-clj-file*)
111124
content-with-missing-paren "(ns test.namespace)\n\n(defn repaired-function [x]\n (+ x 10)"
112-
result (file-write-core/write-clojure-file path content-with-missing-paren)]
125+
result (file-write-core/write-clojure-file
126+
test-utils/*nrepl-client-atom*
127+
path
128+
content-with-missing-paren)]
113129
(is (not (:error result)))
114130
(is (= "update" (:type result)))
115131
(let [saved-content (slurp *test-clj-file*)]
@@ -120,7 +136,10 @@
120136
(testing "Auto-repairs unbalanced brackets"
121137
(let [path (.getPath *test-clj-file*)
122138
content-with-mismatched-brackets "(ns test.namespace)\n\n(defn bracket-fn [x]\n (let [y (+ x 1)]\n (println y]))"
123-
result (file-write-core/write-clojure-file path content-with-mismatched-brackets)]
139+
result (file-write-core/write-clojure-file
140+
test-utils/*nrepl-client-atom*
141+
path
142+
content-with-mismatched-brackets)]
124143
(is (not (:error result)))
125144
(is (= "update" (:type result)))
126145
(let [saved-content (slurp *test-clj-file*)]
@@ -132,7 +151,10 @@
132151
(let [path (.getPath *test-clj-file*)
133152
content-with-syntax-error "(ns test.namespace)\n\n(defn broken-function a123 [x 11)\n (+ x 10))"
134153
original-content (slurp *test-clj-file*)
135-
result (file-write-core/write-clojure-file path content-with-syntax-error)]
154+
result (file-write-core/write-clojure-file
155+
test-utils/*nrepl-client-atom*
156+
path
157+
content-with-syntax-error)]
136158
;; The test should fail with a specific error
137159
(is (:error result) "Should have error for non-repairable syntax error")
138160
(when (:message result)
@@ -145,7 +167,9 @@
145167
(testing "Write dispatcher for Clojure files"
146168
(let [clj-file (io/file *test-dir* "dispatch-test.clj")
147169
content "(ns dispatch.test)"
148-
result (file-write-core/write-file (.getPath clj-file) content)]
170+
result (file-write-core/write-file test-utils/*nrepl-client-atom*
171+
(.getPath clj-file)
172+
content)]
149173
(is (not (:error result)))
150174
(is (= "create" (:type result)))
151175
(is (.exists clj-file))
@@ -154,7 +178,9 @@
154178
(testing "Write dispatcher for text files"
155179
(let [txt-file (io/file *test-dir* "dispatch-test.txt")
156180
content "Plain text content"
157-
result (file-write-core/write-file (.getPath txt-file) content)]
181+
result (file-write-core/write-file test-utils/*nrepl-client-atom*
182+
(.getPath txt-file)
183+
content)]
158184
(is (not (:error result)))
159185
(is (= "create" (:type result)))
160186
(is (.exists txt-file))

test/clojure_mcp/tools/form_edit/core_test.clj

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
(ns clojure-mcp.tools.form-edit.core-test
22
(:require
3+
[clojure-mcp.tools.test-utils :as test-utils]
4+
[clojure-mcp.config :as config]
35
[clojure.test :refer [deftest testing is use-fixtures]]
46
[clojure-mcp.tools.form-edit.core :as sut]
57
[rewrite-clj.zip :as z]
@@ -18,12 +20,14 @@
1820
(spit test-file "(ns test.core)\n\n(defn example-fn [x y]\n #_(println \"debug value:\" x)\n (+ x y))\n\n(def a 1)\n\n#_(def unused-value 42)\n\n(comment\n (example-fn 1 2))\n\n;; Test comment\n;; spans multiple lines")
1921
(binding [*test-dir* test-dir
2022
*test-file* test-file]
23+
(config/set-config! test-utils/*nrepl-client-atom* :nrepl-user-dir test-dir)
2124
(try
2225
(f)
2326
(finally
2427
(when (.exists test-file) (.delete test-file))
2528
(when (.exists test-dir) (.delete test-dir))))))))
2629

30+
(use-fixtures :once test-utils/test-nrepl-fixture)
2731
(use-fixtures :each create-test-files-fixture)
2832

2933
;; Test helper functions
@@ -305,10 +309,21 @@
305309
(deftest format-source-string-test
306310
(testing "format-source-string correctly formats source code"
307311
(let [unformatted "(defn example-fn[x y] (+ x y) )"
308-
formatted (sut/format-source-string unformatted)]
312+
formatted (sut/format-source-string
313+
unformatted
314+
sut/default-formatting-options)]
309315
;; Compare as EDN to ignore whitespace differences
310316
(is (= (read-string unformatted) (read-string formatted))))))
311317

318+
(deftest project-formatting-options-test
319+
(testing "format-source-string correctly formats source code"
320+
(let [custom-options {:function-arguments-indentation :cursive}
321+
_ (spit (io/file *test-dir* "cljfmt.edn") (pr-str custom-options))
322+
formatting-options (sut/project-formatting-options
323+
@test-utils/*nrepl-client-atom*)]
324+
(is (= (merge sut/default-formatting-options custom-options)
325+
formatting-options)))))
326+
312327
(deftest load-file-content-test
313328
(testing "load-file-content loads existing file"
314329
(let [path (.getAbsolutePath *test-file*)

test/clojure_mcp/tools/form_edit/pipeline_test.clj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns clojure-mcp.tools.form-edit.pipeline-test
22
(:require
33
[clojure.test :refer [deftest testing is use-fixtures]]
4+
[clojure-mcp.config :as config]
45
[clojure-mcp.tools.form-edit.pipeline :as sut]
56
[clojure-mcp.tools.form-edit.core :as core]
67
[clojure-mcp.tools.test-utils :as test-utils]
@@ -11,7 +12,6 @@
1112
;; Test fixtures
1213
(def ^:dynamic *test-dir* nil)
1314
(def ^:dynamic *test-file* nil)
14-
1515
(def ^:dynamic *nrepl-client-atom* nil)
1616

1717
(defn create-test-files-fixture [f]
@@ -29,6 +29,7 @@
2929
test-file-content)]
3030
(binding [*test-dir* test-dir
3131
*test-file* (io/file test-file-path)]
32+
(config/set-config! test-utils/*nrepl-client-atom* :nrepl-user-dir test-dir)
3233
(try
3334
(f)
3435
(finally
@@ -175,7 +176,8 @@
175176
(testing "format-source formats the source code"
176177
;; Manual setup to avoid dependency on zloc->output-source
177178
(let [source "(ns test.core)\n\n(defn example-fn[x y] (+ x y))"
178-
ctx {::sut/output-source source} ;; Directly use the source as output source
179+
ctx {::sut/nrepl-client-atom *nrepl-client-atom*
180+
::sut/output-source source} ;; Directly use the source as output source
179181
result (sut/format-source ctx)]
180182
(is (string? (::sut/output-source result)))
181183
(is (not (str/includes? (::sut/output-source result) " example-fn[x y]")))

test/clojure_mcp/tools/test_utils.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns clojure-mcp.tools.test-utils
22
"Utility functions for testing the tool-system based tools."
33
(:require
4+
[clojure-mcp.config :as config]
45
[clojure-mcp.nrepl :as nrepl]
56
[nrepl.server :as nrepl-server]
67
[clojure-mcp.tool-system :as tool-system]

0 commit comments

Comments
 (0)