Skip to content

Commit 09fb950

Browse files
committed
Support workspace/willRenameFiles allowing to rename ns, renaming the files properly
1 parent dc39be4 commit 09fb950

File tree

7 files changed

+97
-61
lines changed

7 files changed

+97
-61
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## [Unreleased]
44

55
- Support Create workspace edit operation. Fixes #51
6+
- Support Rename workspace edit operation
7+
- Support workspace/willRenameFiles allowing to rename ns, renaming the files properly.
68

79
## 2.5.0
810

docs/capabilities.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Below are all the currently supported LSP capabilities and their implementation
2727
| workspace/symbol | | |
2828
| workspace/executeCommand || |
2929
| workspace/applyEdit || |
30-
| workspace/willRenameFiles | | |
30+
| workspace/willRenameFiles | | |
3131
| workspace/didRenameFiles | | |
3232
| workspace/willCreateFiles | | |
3333
| workspace/didCreateFiles | | |
Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
(ns com.github.clojure-lsp.intellij.editor
22
(:require
33
[clojure-lsp.shared :as lsp.shared]
4-
[clojure.java.io :as io]
54
[com.github.clojure-lsp.intellij.editor :as editor]
6-
[com.github.ericdallo.clj4intellij.app-manager :as app-manager]
75
[com.github.ericdallo.clj4intellij.util :as util])
86
(:import
97
[com.intellij.openapi.editor Document Editor]
@@ -12,7 +10,7 @@
1210
[com.intellij.openapi.project Project ProjectLocator]
1311
[com.intellij.openapi.util TextRange]
1412
[com.intellij.openapi.util.text StringUtil]
15-
[com.intellij.openapi.vfs VfsUtil VirtualFile]
13+
[com.intellij.openapi.vfs VirtualFile]
1614
[com.intellij.psi PsiFile]
1715
[com.intellij.psi PsiManager]))
1816

@@ -56,56 +54,3 @@
5654
(defn v-file->project ^Project [^VirtualFile v-file]
5755
(.guessProjectForFile (ProjectLocator/getInstance)
5856
v-file))
59-
60-
(defn ^:private create-document
61-
[{:keys [uri]}]
62-
(let [f (io/file (java.net.URI. uri))
63-
parent-vfile (VfsUtil/createDirectories (.getAbsolutePath (.getParentFile f)))]
64-
(.findOrCreateChildData parent-vfile nil (.getName f))))
65-
66-
(defn ^:private apply-document-change
67-
[{{:keys [uri]} :text-document :keys [edits]} project move-caret?]
68-
(let [editor (util/uri->editor uri project false)
69-
document (.getDocument editor)
70-
sorted-edits (sort-by (comp #(document+position->offset % document) :start :range) > edits)]
71-
(doseq [{:keys [new-text range]} sorted-edits
72-
:let [start (document+position->offset (:start range) document)
73-
end (document+position->offset (:end range) document)]]
74-
(cond
75-
(>= end 0)
76-
(if (<= (- end start) 0)
77-
(.insertString document start new-text)
78-
(.replaceString document start end new-text))
79-
80-
(= 0 start)
81-
(.setText document new-text)
82-
83-
(> start 0)
84-
(.insertString document start new-text)
85-
86-
:else
87-
(.insertString document (.getTextLength document) (str "\n" new-text)))
88-
(when move-caret?
89-
(.moveToOffset (.getCaretModel editor)
90-
(+ (count new-text) start))))
91-
(.saveDocument (FileDocumentManager/getInstance) document)))
92-
93-
(defn apply-workspace-edit ^Boolean
94-
[^Project project label move-caret? {:keys [document-changes]}]
95-
;; TODO Handle more resourceOperations like renaming and deleting files
96-
;; TODO Improve to check version to known if file changed
97-
(app-manager/invoke-later!
98-
{:invoke-fn
99-
(fn []
100-
(app-manager/write-action!
101-
{:run-fn
102-
(fn []
103-
(app-manager/execute-command!
104-
{:name label
105-
:project project
106-
:command-fn
107-
(fn []
108-
(doseq [document-change document-changes]
109-
(case (:kind document-change)
110-
"create" (create-document document-change)
111-
(apply-document-change document-change project move-caret?))))}))}))}))

src/main/clojure/com/github/clojure_lsp/intellij/extension/rename.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
(:require
66
[com.github.clojure-lsp.intellij.client :as lsp-client]
77
[com.github.clojure-lsp.intellij.editor :as editor]
8+
[com.github.clojure-lsp.intellij.file-system :as file-system]
89
[com.github.ericdallo.clj4intellij.util :as util])
910
(:import
1011
[com.intellij.openapi.actionSystem CommonDataKeys DataContext]
@@ -53,4 +54,4 @@
5354
:position {:line line
5455
:character character}
5556
:new-name new-name}])
56-
(editor/apply-workspace-edit project "LSP Rename" true))))))))
57+
(file-system/apply-workspace-edit project "LSP Rename" true))))))))

src/main/clojure/com/github/clojure_lsp/intellij/file_system.clj

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
(ns com.github.clojure-lsp.intellij.file-system
22
(:require
33
[clojure.java.io :as io]
4+
[com.github.clojure-lsp.intellij.client :as lsp-client]
45
[com.github.clojure-lsp.intellij.config :as config]
6+
[com.github.clojure-lsp.intellij.editor :as editor]
7+
[com.github.ericdallo.clj4intellij.app-manager :as app-manager]
8+
[com.github.ericdallo.clj4intellij.util :as util]
59
[com.rpl.proxy-plus :refer [proxy+]])
610
(:import
11+
[com.intellij.openapi.fileEditor
12+
FileDocumentManager]
713
[com.intellij.openapi.project Project]
8-
[com.intellij.openapi.vfs LocalFileSystem VirtualFile]))
14+
[com.intellij.openapi.vfs LocalFileSystem VfsUtil VirtualFile]
15+
[java.net URI]))
916

1017
(set! *warn-on-reflection* true)
1118

@@ -30,3 +37,81 @@
3037
(getInputStream [_] (io/input-stream temp-file))
3138
(getOutputStream [_ _ _ _] (io/output-stream temp-file))
3239
(getModificationStamp [_] -1))))
40+
41+
(defn ^:private create-document
42+
[{:keys [uri]}]
43+
(let [f (io/file (URI. uri))
44+
parent-vfile (VfsUtil/createDirectories (.getAbsolutePath (.getParentFile f)))]
45+
(.findOrCreateChildData parent-vfile nil (.getName f))))
46+
47+
(declare apply-workspace-edit-sync)
48+
49+
(defn will-rename-file [project old-uri new-uri]
50+
(let [client (lsp-client/connected-client project)]
51+
(->> (lsp-client/request! client [:workspace/willRenameFiles
52+
{:files [{:old-uri old-uri
53+
:new-uri new-uri}]}])
54+
deref
55+
(apply-workspace-edit-sync project false))))
56+
57+
(defn ^:private rename-document
58+
[{:keys [old-uri new-uri]} project]
59+
(will-rename-file project old-uri new-uri)
60+
(let [old-file (io/file (URI. old-uri))
61+
new-file (io/file (URI. new-uri))
62+
vfile (util/uri->v-file old-uri)]
63+
(.rename vfile nil (.getName new-file))
64+
(when-not (= (.getAbsolutePath (.getParentFile old-file))
65+
(.getAbsolutePath (.getParentFile new-file)))
66+
(.move vfile nil (util/uri->v-file (str (.toURI (.getParentFile new-file))))))))
67+
68+
(defn ^:private apply-document-change
69+
[{{:keys [uri]} :text-document :keys [edits]} project move-caret?]
70+
(let [editor (util/uri->editor uri project false)
71+
document (.getDocument editor)
72+
sorted-edits (sort-by (comp #(editor/document+position->offset % document) :start :range) > edits)]
73+
(doseq [{:keys [new-text range]} sorted-edits
74+
:let [start (editor/document+position->offset (:start range) document)
75+
end (editor/document+position->offset (:end range) document)]]
76+
(cond
77+
(>= end 0)
78+
(if (<= (- end start) 0)
79+
(.insertString document start new-text)
80+
(.replaceString document start end new-text))
81+
82+
(= 0 start)
83+
(.setText document new-text)
84+
85+
(> start 0)
86+
(.insertString document start new-text)
87+
88+
:else
89+
(.insertString document (.getTextLength document) (str "\n" new-text)))
90+
(when move-caret?
91+
(.moveToOffset (.getCaretModel editor)
92+
(+ (count new-text) start))))
93+
(.saveDocument (FileDocumentManager/getInstance) document)))
94+
95+
(defn ^:private apply-workspace-edit-sync [project move-caret? {:keys [document-changes]}]
96+
(doseq [document-change document-changes]
97+
(case (:kind document-change)
98+
"create" (create-document document-change)
99+
"rename" (rename-document document-change project)
100+
(apply-document-change document-change project move-caret?))))
101+
102+
(defn apply-workspace-edit ^Boolean
103+
[^Project project label move-caret? edit]
104+
;; TODO Handle more resourceOperations like renaming and deleting files
105+
;; TODO Improve to check version to known if file changed
106+
(app-manager/invoke-later!
107+
{:invoke-fn
108+
(fn []
109+
(app-manager/write-action!
110+
{:run-fn
111+
(fn []
112+
(app-manager/execute-command!
113+
{:name label
114+
:project project
115+
:command-fn
116+
(fn []
117+
(apply-workspace-edit-sync project move-caret? edit))}))}))}))

src/main/clojure/com/github/clojure_lsp/intellij/server.clj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
(def ^:private client-capabilities
2424
{:text-document {:hover {:content-format ["markdown"]}
2525
:implementation {}}
26-
:workspace {:workspace-edit {:document-changes true}}
26+
:workspace {:workspace-edit {:document-changes true
27+
:resource-operations ["create" "rename"]}
28+
:file-operations {:will-rename true}}
2729
:window {:show-document true}})
2830

2931
(def ^:private artifacts

src/main/clojure/com/github/clojure_lsp/intellij/workspace_edit.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
(:require
33
[com.github.clojure-lsp.intellij.client :as lsp-client]
44
[com.github.clojure-lsp.intellij.editor :as editor]
5+
[com.github.clojure-lsp.intellij.file-system :as file-system]
56
[com.github.ericdallo.clj4intellij.app-manager :as app-manager]
67
[com.github.ericdallo.clj4intellij.logger :as logger]
78
[com.github.ericdallo.clj4intellij.util :as util]))
89

910
(set! *warn-on-reflection* true)
1011

1112
(defmethod lsp-client/workspace-apply-edit :default [{:keys [project]} {:keys [label edit]}]
12-
(editor/apply-workspace-edit project label false edit)
13+
(file-system/apply-workspace-edit project label false edit)
1314
{:applied true})
1415

1516
(defmethod lsp-client/show-document :default [{:keys [project]} {:keys [uri take-focus selection]}]

0 commit comments

Comments
 (0)