Skip to content

Commit e1e2a49

Browse files
authored
Add support for inlay hints from TypeScript language server (#3455)
1 parent 6bc8a39 commit e1e2a49

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

CHANGELOG.org

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
* Add [[https://github.com/aca/emmet-ls][emmet-ls]]
2929
* Support all ~initializationOptions~ in ~typescript-language-server~
3030
* Update rust-analyzer's inlay hint protocol support.
31+
* Add support for ~typescript-language-server~’s inlay hints.
3132
** Release 8.0.0
3233
* Add ~lsp-clients-angular-node-get-prefix-command~ to get the Angular server from another location which is still has ~/lib/node_modules~ in it.
3334
* Set ~lsp-clients-angular-language-server-command~ after the first connection to speed up subsequent connections.

clients/lsp-javascript.el

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,12 +600,88 @@ TypeScript 3.0 or newer in the workspace."
600600
:type 'boolean
601601
:package-version '(lsp-mode . "6.1"))
602602

603+
;; inlay hints
604+
605+
(defface lsp-javascript-inlay-face
606+
'((t :inherit font-lock-comment-face))
607+
"The face to use for the JavaScript inlays."
608+
:group 'lsp-javascript
609+
:package-version '(lsp-mode . "8.0.1"))
610+
611+
(defface lsp-javascript-inlay-type-face
612+
'((t :inherit lsp-javascript-inlay-face))
613+
"Face for inlay type hints (e.g. inferred variable types)."
614+
:group 'lsp-javascript
615+
:package-version '(lsp-mode . "8.0.1"))
616+
617+
(defcustom lsp-javascript-inlay-type-format ": %s"
618+
"Format string for variable inlays (part of the inlay face)."
619+
:type '(string :tag "String")
620+
:group 'lsp-javascript
621+
:package-version '(lsp-mode . "8.0.1"))
622+
623+
(defface lsp-javascript-inlay-parameter-face
624+
'((t :inherit lsp-javascript-inlay-face))
625+
"Face for inlay parameter hints (e.g. function parameter names at
626+
call-site)."
627+
:group 'lsp-javascript
628+
:package-version '(lsp-mode . "8.0.1"))
629+
630+
(defcustom lsp-javascript-inlay-param-format "%s:"
631+
"Format string for parameter inlays (part of the inlay face)."
632+
:type '(string :tag "String")
633+
:group 'lsp-javascript
634+
:package-version '(lsp-mode . "8.0.1"))
635+
603636
(defcustom lsp-typescript-surveys-enabled t
604637
"Enabled/disable occasional surveys that help us improve VS
605638
Code's JavaScript and TypeScript support."
606639
:type 'boolean
607640
:package-version '(lsp-mode . "6.1"))
608641

642+
(defcustom lsp-javascript-display-inlay-hints nil
643+
"Whether to display inlay hints."
644+
:type 'boolean
645+
:package-version '(lsp-mode . "8.0.1"))
646+
647+
(defcustom lsp-javascript-display-enum-member-value-hints nil
648+
"Show inlay hints for enum member values."
649+
:type 'boolean
650+
:package-version '(lsp-mode . "8.0.1"))
651+
652+
(defcustom lsp-javascript-display-return-type-hints nil
653+
"Show inlay hints for function return types."
654+
:type 'boolean
655+
:package-version '(lsp-mode . "8.0.1"))
656+
657+
(defcustom lsp-javascript-display-parameter-type-hints nil
658+
"Show inlay hints for function parameters."
659+
:type 'boolean
660+
:package-version '(lsp-mode . "8.0.1"))
661+
662+
(defcustom lsp-javascript-display-parameter-name-hints "none"
663+
"Level of hinting for parameter types."
664+
:type '(choice (const :tag "none" "none")
665+
(const :tag "literals" "literals")
666+
(const :tag "all" "all"))
667+
:package-version '(lsp-mode . "8.0.1"))
668+
669+
(defcustom lsp-javascript-display-parameter-name-hints-when-argument-matches-name nil
670+
"Show inlay hints for function parameters even when argument matches
671+
name (e.g. `data' variable passed as `data' parameter)."
672+
:type 'boolean
673+
:package-version '(lsp-mode . "8.0.1"))
674+
675+
(defcustom lsp-javascript-display-property-declaration-type-hints nil
676+
"Show inlay hints for property declaration types."
677+
:type 'boolean
678+
:package-version '(lsp-mode . "8.0.1"))
679+
680+
(defcustom lsp-javascript-display-variable-type-hints nil
681+
"Show inlay hints for variable types."
682+
:type 'boolean
683+
:package-version '(lsp-mode . "8.0.1"))
684+
609685
(lsp-register-custom-settings
610686
'(("javascript.autoClosingTags" lsp-javascript-auto-closing-tags t)
611687
("javascript.implicitProjectConfig.checkJs" lsp-javascript-implicit-project-config-check-js t)
@@ -678,7 +754,21 @@ Code's JavaScript and TypeScript support."
678754
("typescript.format.insertSpaceBeforeAndAfterBinaryOperators" lsp-typescript-format-insert-space-before-and-after-binary-operators t)
679755
("typescript.format.insertSpaceBeforeFunctionParenthesis" lsp-typescript-format-insert-space-before-function-parenthesis t)
680756
("typescript.format.placeOpenBraceOnNewLineForControlBlocks" lsp-typescript-format-place-open-brace-on-new-line-for-control-blocks t)
681-
("typescript.format.placeOpenBraceOnNewLineForFunctions" lsp-typescript-format-place-open-brace-on-new-line-for-functions t)))
757+
("typescript.format.placeOpenBraceOnNewLineForFunctions" lsp-typescript-format-place-open-brace-on-new-line-for-functions t)
758+
("typescript.inlayHints.includeInlayEnumMemberValueHints" lsp-javascript-display-enum-member-value-hints t)
759+
("typescript.inlayHints.includeInlayFunctionLikeReturnTypeHints" lsp-javascript-display-return-type-hints t)
760+
("typescript.inlayHints.includeInlayFunctionParameterTypeHints" lsp-javascript-display-parameter-type-hints t)
761+
("typescript.inlayHints.includeInlayParameterNameHints" lsp-javascript-display-parameter-name-hints nil)
762+
("typescript.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName" lsp-javascript-display-parameter-name-hints-when-argument-matches-name t)
763+
("typescript.inlayHints.includeInlayPropertyDeclarationTypeHints" lsp-javascript-display-property-declaration-type-hints t)
764+
("typescript.inlayHints.includeInlayVariableTypeHints" lsp-javascript-display-variable-type-hints t)
765+
("javascript.inlayHints.includeInlayEnumMemberValueHints" lsp-javascript-display-enum-member-value-hints t)
766+
("javascript.inlayHints.includeInlayFunctionLikeReturnTypeHints" lsp-javascript-display-return-type-hints t)
767+
("javascript.inlayHints.includeInlayFunctionParameterTypeHints" lsp-javascript-display-parameter-type-hints t)
768+
("javascript.inlayHints.includeInlayParameterNameHints" lsp-javascript-display-parameter-name-hints nil)
769+
("javascript.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName" lsp-javascript-display-parameter-name-hints-when-argument-matches-name t)
770+
("javascript.inlayHints.includeInlayPropertyDeclarationTypeHints" lsp-javascript-display-property-declaration-type-hints t)
771+
("javascript.inlayHints.includeInlayVariableTypeHints" lsp-javascript-display-variable-type-hints t)))
682772

683773
(lsp-dependency 'typescript-language-server
684774
'(:system lsp-clients-typescript-tls-path)
@@ -727,6 +817,56 @@ Code's JavaScript and TypeScript support."
727817
(lsp)
728818
(lsp--info "Renamed '%s' to '%s'." name (file-name-nondirectory new)))))
729819

820+
(defun lsp-javascript-update-inlay-hints ()
821+
(if (lsp-javascript-initialized?)
822+
(lsp-request-async
823+
"typescript/inlayHints"
824+
(lsp-make-javascript-inlay-hints-params
825+
:text-document (lsp--text-document-identifier))
826+
(lambda (res)
827+
(lsp--remove-overlays 'lsp-javascript-inlay-hint)
828+
(-each (gethash "inlayHints" res)
829+
#'(lambda (hint)
830+
(-let* (((&javascript:InlayHint :text :position :kind :whitespace-before? :whitespace-after?) hint)
831+
(pos (lsp--position-to-point position))
832+
(overlay (make-overlay pos pos nil 'front-advance 'end-advance)))
833+
(overlay-put overlay 'lsp-javascript-inlay-hint t)
834+
(overlay-put overlay 'before-string
835+
(format "%s%s%s"
836+
(if (and whitespace-before? (not (string= kind lsp/javascript-inlay-hint-kind-type-hint))) " " "")
837+
(propertize (lsp-javascript-format-inlay text kind)
838+
'font-lock-face (lsp-javascript-face-for-inlay kind))
839+
(if whitespace-after? " " ""))))))))
840+
:mode 'tick))
841+
842+
(defun lsp-javascript-format-inlay (text kind)
843+
(cond
844+
((eql kind lsp/javascript-inlay-hint-kind-type-hint) (format lsp-javascript-inlay-type-format text))
845+
((eql kind lsp/javascript-inlay-hint-kind-parameter-hint) (format lsp-javascript-inlay-param-format text))
846+
;; ((eql kind lsp/javascript-inlay-hint-kind-enum-hint) (format lsp-javascript-inlay-enum-format text))
847+
(t text)))
848+
849+
(defun lsp-javascript-face-for-inlay (kind)
850+
(cond
851+
((eql kind lsp/javascript-inlay-hint-kind-type-hint) 'lsp-javascript-inlay-type-face)
852+
((eql kind lsp/javascript-inlay-hint-kind-parameter-hint) 'lsp-javascript-inlay-parameter-face)
853+
(t 'lsp-javascript-inlay-face)))
854+
855+
(defun lsp-javascript-initialized? ()
856+
(when-let ((workspace (lsp-find-workspace 'ts-ls (buffer-file-name))))
857+
(eq 'initialized (lsp--workspace-status workspace))))
858+
859+
(define-minor-mode lsp-javascript-inlay-hints-mode
860+
"Mode for displaying inlay hints."
861+
:lighter nil
862+
(cond
863+
(lsp-javascript-inlay-hints-mode
864+
(lsp-javascript-update-inlay-hints)
865+
(add-hook 'lsp-on-idle-hook #'lsp-javascript-update-inlay-hints nil t))
866+
(t
867+
(lsp--remove-overlays 'lsp-javascript-inlay-hint)
868+
(remove-hook 'lsp-on-idle-hook #'lsp-javascript-update-inlay-hints t))))
869+
730870
(lsp-register-client
731871
(make-lsp-client :new-connection (lsp-stdio-connection (lambda ()
732872
`(,(lsp-package-path 'typescript-language-server)
@@ -748,6 +888,9 @@ Code's JavaScript and TypeScript support."
748888
(lsp--set-configuration
749889
(ht-merge (lsp-configuration-section "javascript")
750890
(lsp-configuration-section "typescript")))))
891+
:after-open-fn (lambda ()
892+
(when lsp-javascript-display-inlay-hints
893+
(lsp-javascript-inlay-hints-mode)))
751894
:ignore-messages '("readFile .*? requested by TypeScript but content not available")
752895
:server-id 'ts-ls
753896
:request-handlers (ht ("_typescript.rename" #'lsp-javascript--rename))

lsp-protocol.el

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,12 @@ See `-let' for a description of the destructuring mechanism."
421421
(rust-analyzer:CommandLink (:title :command) (:arguments :tooltip))
422422
(rust-analyzer:CommandLinkGroup (:commands) (:title)))
423423

424+
(defconst lsp/javascript-inlay-hint-kind-type-hint "Type")
425+
(defconst lsp/javascript-inlay-hint-kind-parameter-hint "Parameter")
426+
(defconst lsp/javascript-inlay-hint-kind-enum-hint "Enum")
427+
(lsp-interface (javascript:InlayHint (:text :position :kind) (:whitespaceBefore :whitespaceAfter))
428+
(javascript:InlayHintsParams (:textDocument) (:range)))
429+
424430
(lsp-interface (clojure-lsp:TestTreeParams (:uri :tree) nil)
425431
(clojure-lsp:TestTreeNode (:name :range :nameRange :kind) (:children)))
426432

0 commit comments

Comments
 (0)