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

Construct error relaxation #10

Merged
merged 2 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions ocaml-eglot-req.el
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,19 @@ CANCEL-ON-INPUT-RETVAL are hooks for cancellation."
(eglot--TextDocumentPositionParams)
(ocaml-eglot-req--TextDocumentIdentifier)))

(defun ocaml-eglot-req--ConstructParams (depth with-local-values)
(defun ocaml-eglot-req--TextDocumentPositionParamsWithPos (position)
"Compute `TextDocumentPositionParams' object for the current buffer.
With a given POSITION"
(append (list :textDocument (ocaml-eglot-req--TextDocumentIdentifier)
:position position)
(ocaml-eglot-req--TextDocumentIdentifier)))

(defun ocaml-eglot-req--ConstructParams (position depth with-local-values)
"Compute `ConstructParams' object for current buffer.
POSITION the position of the hole.
DEPTH is the depth of the search (default is 1).
WITH-LOCAL-VALUES is a flag for including local values in construction."
(append (ocaml-eglot-req--TextDocumentPositionParams)
(append (ocaml-eglot-req--TextDocumentPositionParamsWithPos position)
`(:depth, depth)
`(:withValues, with-local-values)))

Expand Down Expand Up @@ -99,10 +107,11 @@ A potential IDENTIFIER can be given and MARKUP-KIND can be parametrized."
(let ((params (ocaml-eglot-req--TextDocumentPositionParams)))
(ocaml-eglot-req--send :ocamllsp/jump params)))

(defun ocaml-eglot-req--construct (depth with-local-value)
"Execute the `ocamllsp/construct' request.
(defun ocaml-eglot-req--construct (position depth with-local-value)
"Execute the `ocamllsp/construct' request for a given POSITION.
DEPTH and WITH-LOCAL-VALUE can be parametrized."
(let ((params (ocaml-eglot-req--ConstructParams depth with-local-value)))
(let ((params (ocaml-eglot-req--ConstructParams
position depth with-local-value)))
(ocaml-eglot-req--send :ocamllsp/construct params)))

(defun ocaml-eglot-req--search (query limit with-doc markup-kind)
Expand Down
10 changes: 10 additions & 0 deletions ocaml-eglot-util.el
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@
"Format MARKUP according to LSP's spec."
(eglot--format-markup markup))

(defun ocaml-eglot-util--current-range ()
"Return the current active range."
(if (region-active-p)
(let ((region-start (region-beginning))
(region-stop (region-end)))
(list :start (eglot--pos-to-lsp-position region-start)
:end (eglot--pos-to-lsp-position region-stop)))
(let ((start (eglot--pos-to-lsp-position)))
(list :start start
:end (ocaml-eglot-util--position-increase-char start "_")))))

(provide 'ocaml-eglot-util)
;;; ocaml-eglot-util.el ends here
57 changes: 35 additions & 22 deletions ocaml-eglot.el
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,22 @@ If there is no available holes, it returns the first one of HOLES."
(let ((hole (ocaml-eglot--first-hole-aux holes pos comparison)))
(if hole hole (car holes))))

(defun ocaml-eglot--first-hole-in (start end)
"Jump to the first hole in a given range denoted by START and END."
(defun ocaml-eglot--get-first-hole-in (start end)
"Return the first hole in a given range denoted by START and END."
(let* ((holes (ocaml-eglot-req--holes))
(hole (ocaml-eglot--first-hole-at holes start '>)))
(hole (ocaml-eglot--first-hole-at holes start '>=)))
(when hole
(let ((hole-start (cl-getf hole :start))
(hole-end (cl-getf hole :end)))
(when (and (>= (ocaml-eglot-util--compare-position hole-start start) 0)
(<= (ocaml-eglot-util--compare-position hole-end end) 0))
(ocaml-eglot-util--jump-to hole-start))))))
hole)))))

(defun ocaml-eglot--first-hole-in (start end)
"Jump to the first hole in a given range denoted by START and END."
(when-let ((hole (ocaml-eglot--get-first-hole-in start end))
(hole-start (cl-getf hole :start)))
(ocaml-eglot-util--jump-to hole-start)))

(defun ocaml-eglot-hole-prev ()
"Jump to the previous hole."
Expand Down Expand Up @@ -310,24 +316,31 @@ of result (LIMIT)."
It use the ARG to use local values or not."
(interactive "P")
(eglot--server-capable-or-lose :experimental :ocamllsp :handleConstruct)
(let* ((with-local-value (ocaml-eglot--construct-local-values arg))
(result (ocaml-eglot-req--construct 1 with-local-value))
(range (cl-getf result :position))
(suggestions (append (cl-getf result :result) nil)))
(when (= (length suggestions) 0)
(eglot--error "No constructors for this hole"))
(cl-labels
((insert-construct-choice (subst)
(let* ((start (cl-getf range :start))
(end (ocaml-eglot-util--position-increase-char
start subst)))
(ocaml-eglot-util--replace-region range subst)
(ocaml-eglot--first-hole-in start end))))
(if (= (length suggestions) 1)
(insert-construct-choice (car suggestions))
(let ((choice (completing-read "Constructor: " suggestions nil t)))
(insert-construct-choice choice))))))

(let* ((_with-local-values (ocaml-eglot--construct-local-values arg))
(current-range (ocaml-eglot-util--current-range))
(start (cl-getf current-range :start))
(end (cl-getf current-range :end))
(hole (ocaml-eglot--get-first-hole-in start end)))
(if (not hole)
(eglot--error "Not a hole")
(let* ((with-local-value (ocaml-eglot--construct-local-values arg))
(hole-start (cl-getf hole :start))
(result (ocaml-eglot-req--construct hole-start 1 with-local-value))
(range (cl-getf result :position))
(suggestions (append (cl-getf result :result) nil)))
(when (= (length suggestions) 0)
(eglot--error "No constructors for this hole"))
(cl-labels
((insert-construct-choice (subst)
(let* ((start (cl-getf range :start))
(end (ocaml-eglot-util--position-increase-char
start subst)))
(ocaml-eglot-util--replace-region range subst)
(ocaml-eglot--first-hole-in start end))))
(if (= (length suggestions) 1)
(insert-construct-choice (car suggestions))
(let ((choice (completing-read "Constructor: " suggestions nil t)))
(insert-construct-choice choice))))))))

;; Get Documentation

Expand Down
Loading