Skip to content

Commit

Permalink
Do not resolve during annotate, enrich documentation with details (Fix
Browse files Browse the repository at this point in the history
…#3201) (Fix #3905) (#4625)

* Do not resolve during annotate, enrich documentation with details

Also fixes:

- #3201
- #3905

* cache adjusted documentation

* Make lsp-completion--resolve[-async] public

* Resolved detail may be different from unresolved detail

* Do not fontify detail in documentation

* Return resolved signature via company-docsig

* Properly implement labelDetails for 3.17

* Show detail when labelDetail is not available

* Replace \r only when there's a detail

* Request server to compute insertTextFormat and insertTextMode early

* Use code fence for detail

* Put lsp-completion-show-detail back
  • Loading branch information
wyuenho authored Jan 10, 2025
1 parent d28dd6b commit 17483ec
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 29 deletions.
118 changes: 93 additions & 25 deletions lsp-completion.el
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ ignored."
:type 'boolean
:group 'lsp-completion)

(defcustom lsp-completion-show-label-description t
"Whether or not to show description of completion candidates."
:type 'boolean
:group 'lsp-completion
:package-version '(lsp-mode . "9.0.0"))

(defcustom lsp-completion-no-cache nil
"Whether or not caching the returned completions from server."
:type 'boolean
Expand Down Expand Up @@ -172,6 +166,7 @@ This will help minimize popup flickering issue in `company-mode'."
:_emacsStartPoint start-point)
item))
(propertize label
'lsp-completion-unresolved-item item
'lsp-completion-item item
'lsp-sort-text sort-text?
'lsp-completion-start-point start-point
Expand Down Expand Up @@ -245,20 +240,40 @@ The CLEANUP-FN will be called to cleanup."
(funcall callback completion-item)
(when cleanup-fn (funcall cleanup-fn))))))

(defun lsp-completion--annotate (item)
"Annotate ITEM detail."
(-let (((completion-item &as &CompletionItem :detail? :kind? :label-details?)
(get-text-property 0 'lsp-completion-item item)))
(lsp-completion--resolve-async item #'ignore)

(concat (when (and lsp-completion-show-detail detail?)
(concat " " (s-replace "\r" "" detail?)))
(when (and lsp-completion-show-label-description label-details?)
(when-let* ((description (and label-details? (lsp:label-details-description label-details?))))
(format " %s" description)))
(when lsp-completion-show-kind
(when-let* ((kind-name (and kind? (aref lsp-completion--item-kind kind?))))
(format " (%s)" kind-name))))))
(defun lsp-completion--get-label-detail (item &optional omit-description)
"Construct label detail from completion item ITEM."
(-let (((&CompletionItem :detail? :label-details?) item))
(cond ((and label-details?
(or (lsp:label-details-detail? label-details?)
(lsp:label-details-description? label-details?)))
(-let (((&LabelDetails :detail? :description?) label-details?))
(concat
(unless (and detail? (string-prefix-p " " detail?))
" ")
(when detail?
(s-replace "\r" "" detail?))
(unless (or omit-description
(and description? (string-prefix-p " " description?)))
" ")
(unless omit-description
description?))))
(detail?
(concat (unless (and detail? (string-prefix-p " " detail?))
" ")
(s-replace "\r" "" detail?))))))

(defun lsp-completion--annotate (cand)
"Annotation function for completion candidate CAND.
Returns unresolved completion item detail."
(when-let ((lsp-completion-item (get-text-property 0 'lsp-completion-unresolved-item cand)))
(concat
(when lsp-completion-show-detail
(lsp-completion--get-label-detail lsp-completion-item))
(when lsp-completion-show-kind
(when-let* ((kind? (lsp:completion-item-kind? lsp-completion-item))
(kind-name (and kind? (aref lsp-completion--item-kind kind?))))
(format " (%s)" kind-name))))))

(defun lsp-completion--looking-back-trigger-characterp (trigger-characters)
"Return character if text before point match any of the TRIGGER-CHARACTERS."
Expand Down Expand Up @@ -457,13 +472,65 @@ The MARKERS and PREFIX value will be attached to each candidate."
(setq label-pos 0)))
matches)))

(defun lsp-completion--company-docsig (cand)
"Signature for completion candidate CAND.
Returns resolved completion item details."
(and (lsp-completion--resolve cand)
(lsp-completion--get-label-detail
(get-text-property 0 'lsp-completion-item cand)
t)))

(defun lsp-completion--get-documentation (item)
"Get doc comment for completion ITEM."
(-some->> item
(lsp-completion--resolve)
(get-text-property 0 'lsp-completion-item)
(lsp:completion-item-documentation?)
(lsp--render-element)))
(or (get-text-property 0 'lsp-completion-item-doc item)
(-let* (((&CompletionItem :detail?
:documentation?)
(get-text-property 0 'lsp-completion-item (lsp-completion--resolve item)))
(doc
(if (and detail? documentation?)
;; detail was resolved, that means the candidate list has no
;; detail, so we may need to prepend it to the documentation
(cond ((lsp-markup-content? documentation?)
(-let (((&MarkupContent :kind :value) documentation?))
(cond ((and (equal kind "plaintext")
(not (string-match-p (regexp-quote detail?) value)))

(lsp--render-string
(concat detail?
(if (bound-and-true-p page-break-lines-mode)
"\n \n"
"\n\n")
value)
kind))

((and (equal kind "markdown")
(not (string-match-p (regexp-quote detail?) value)))

(lsp--render-string
(concat
"```\n"
detail?
"\n```"
"\n---\n"
value)
kind)))))

((and (stringp documentation?)
(not (string-match-p (regexp-quote detail?) documentation?)))

(lsp--render-string
(concat detail?
(if (bound-and-true-p page-break-lines-mode)
"\n \n"
"\n\n")
documentation?)
"plaintext")))

(lsp--render-element documentation?))))

(put-text-property 0 (length item) 'lsp-completion-item-doc doc item)
doc)))

(defun lsp-completion--get-context (trigger-characters same-session?)
"Get completion context with provided TRIGGER-CHARACTERS and SAME-SESSION?."
Expand Down Expand Up @@ -602,6 +669,7 @@ The MARKERS and PREFIX value will be attached to each candidate."
(goto-char (1- (point))))
(and triggered-by-char? t)))
:company-match #'lsp-completion--company-match
:company-docsig #'lsp-completion--company-docsig
:company-doc-buffer (-compose #'lsp-doc-buffer
#'lsp-completion--get-documentation)
:exit-function
Expand Down
4 changes: 1 addition & 3 deletions lsp-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -3800,9 +3800,7 @@ disappearing, unset all the variables related to it."
. ((properties . ["documentation"
"detail"
"additionalTextEdits"
"command"
"insertTextFormat"
"insertTextMode"])))
"command"])))
(insertTextModeSupport . ((valueSet . [1 2])))
(labelDetailsSupport . t)))
(contextSupport . t)
Expand Down
2 changes: 1 addition & 1 deletion lsp-protocol.el
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,6 @@ See `-let' for a description of the destructuring mechanism."
(FormattingOptions (:tabSize :insertSpaces) (:trimTrailingWhitespace :insertFinalNewline :trimFinalNewlines))
(HoverCapabilities nil (:contentFormat :dynamicRegistration))
(ImplementationCapabilities nil (:dynamicRegistration :linkSupport))
(LabelDetails (:detail :description) nil)
(LinkedEditingRanges (:ranges) (:wordPattern))
(Location (:range :uri) nil)
(MarkedString (:language :value) nil)
Expand Down Expand Up @@ -824,6 +823,7 @@ See `-let' for a description of the destructuring mechanism."
(WillSaveTextDocumentParams (:reason :textDocument) nil)
(WorkspaceSymbolParams (:query) nil)
;; 3.17
(LabelDetails nil (:detail :description))
(InlayHint (:label :position) (:kind :paddingLeft :paddingRight))
(InlayHintLabelPart (:value) (:tooltip :location :command))
(InlayHintsParams (:textDocument) (:range))
Expand Down

0 comments on commit 17483ec

Please sign in to comment.