Skip to content

Commit cce530b

Browse files
committed
OCaml: Add implIntf
*This is the first of a series of PR I aim to do to improve the ocaml-lsp experience in lsp-mode* This PR exposes `lsp-ocaml-find-alternate-file` that allows to find the file interface corresponding to an implementation or the implementation corresponding to an interface. This function is quite simple for the moment since I first needed to make sure that the LSP requests were working as expected. Following PRs will add more possibilities
1 parent ac71048 commit cce530b

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

clients/lsp-ocaml.el

+63
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
;;; Code:
2626

2727
(require 'lsp-mode)
28+
(require 'find-file)
2829

2930
(defgroup lsp-ocaml nil
3031
"LSP support for OCaml, using ocaml-language-server."
@@ -129,6 +130,68 @@ An example of function using STORABLE is:
129130
ntype)))
130131
type)))
131132

133+
;;; OCaml-lsp extensions interface
134+
;;;
135+
;;; The following functions are used to create an interface between custom OCaml-lsp requests and lsp-mode
136+
137+
(defun lsp-ocaml--switch-impl-intf ()
138+
"Switch to the file(s) that the current file can switch to.
139+
140+
OCaml-lsp LSP protocol documented here
141+
https://github.com/ocaml/ocaml-lsp/blob/master/ocaml-lsp-server/docs/ocamllsp/switchImplIntf-spec.md"
142+
(-if-let* ((params (lsp-make-ocaml-lsp-switch-impl-intf-params
143+
:uri (lsp--buffer-uri)))
144+
(uris (lsp-request "ocamllsp/switchImplIntf" params)))
145+
uris
146+
(lsp--warn "Your version of ocaml-lsp doesn't support the switchImplIntf extension")))
147+
148+
;;; OCaml-lsp utilities
149+
150+
(defun lsp-ocaml--has-one-element-p (lst)
151+
"Returns t if LST contains only one element."
152+
(and lst (= (length lst) 1)))
153+
154+
(defun lsp-ocaml--load-uri (uri &optional other-window)
155+
"Check if URI exists and opens its buffer or create a new one.
156+
157+
If OTHER-WINDOW is not nil, opens the buffer in an other window."
158+
(let ((path (lsp--uri-to-path uri)))
159+
(cond
160+
161+
;; A buffer already exists with PATH
162+
((bufferp (get-file-buffer path))
163+
(ff-switch-to-buffer (get-file-buffer path) other-window)
164+
path)
165+
166+
;; PATH is an existing file
167+
((file-exists-p path)
168+
(ff-find-file path other-window nil)
169+
path)
170+
171+
;; PATH is not an existing file
172+
(t
173+
nil))))
174+
175+
(defun lsp-ocaml--find-alternate-uri ()
176+
"Returns the URI corresponding to the alternate file if there's only one or prompt for a choice."
177+
(let ((uris (lsp-ocaml--switch-impl-intf)))
178+
(if (lsp-ocaml--has-one-element-p uris)
179+
(car uris)
180+
(let* ((filenames (mapcar #'f-filename uris))
181+
(selected-file (completing-read "Choose an alternate file " filenames)))
182+
(nth (cl-position selected-file filenames :test #'string=) uris)))))
183+
184+
;;; OCaml-lsp extensions
185+
;;;
186+
;;; The following functions are interactive implementations of the custom OCaml-lsp requests
187+
188+
(defun lsp-ocaml-find-alternate-file ()
189+
"Returns the URI corresponding to the alternate file if there's only one or prompt for a choice."
190+
(interactive)
191+
(let ((uri (lsp-ocaml--find-alternate-uri)))
192+
(unless (lsp-ocaml--load-uri uri nil)
193+
(message "No alternate file %s could be found for %s" (f-filename uri) (buffer-name)))))
194+
132195
(lsp-consistency-check lsp-ocaml)
133196

134197
(provide 'lsp-ocaml)
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
author: mattiasdrp
3+
template: comment.html
4+
root_file: docs/manual-language-docs/lsp-ocaml.md
5+
---
6+
7+
## ocaml-lsp-server
8+
9+
### Commands
10+
11+
#### `lsp-ocaml-find-alternate-file`
12+
13+
Find the interface corresponding to an implementation or the implementation corresponding to an interface.

lsp-protocol.el

+2
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ See `-let' for a description of the destructuring mechanism."
433433
(lsp-interface (csharp-ls:CSharpMetadata (:textDocument))
434434
(csharp-ls:CSharpMetadataResponse (:source :projectName :assemblyName :symbolName)))
435435

436+
(lsp-interface (ocaml-lsp:SwitchImplIntfParams (:uri) nil))
437+
436438
(lsp-interface (rls:Cmd (:args :binary :env :cwd) nil))
437439

438440
(lsp-interface (rust-analyzer:AnalyzerStatusParams (:textDocument))

0 commit comments

Comments
 (0)