Skip to content

Commit

Permalink
Add support for inlay hints from TypeScript language server (#3455)
Browse files Browse the repository at this point in the history
  • Loading branch information
shivjm authored Apr 9, 2022
1 parent 6bc8a39 commit e1e2a49
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.org
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* Add [[https://github.com/aca/emmet-ls][emmet-ls]]
* Support all ~initializationOptions~ in ~typescript-language-server~
* Update rust-analyzer's inlay hint protocol support.
* Add support for ~typescript-language-server~’s inlay hints.
** Release 8.0.0
* 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.
* Set ~lsp-clients-angular-language-server-command~ after the first connection to speed up subsequent connections.
Expand Down
145 changes: 144 additions & 1 deletion clients/lsp-javascript.el
Original file line number Diff line number Diff line change
Expand Up @@ -600,12 +600,88 @@ TypeScript 3.0 or newer in the workspace."
:type 'boolean
:package-version '(lsp-mode . "6.1"))

;; inlay hints

(defface lsp-javascript-inlay-face
'((t :inherit font-lock-comment-face))
"The face to use for the JavaScript inlays."
:group 'lsp-javascript
:package-version '(lsp-mode . "8.0.1"))

(defface lsp-javascript-inlay-type-face
'((t :inherit lsp-javascript-inlay-face))
"Face for inlay type hints (e.g. inferred variable types)."
:group 'lsp-javascript
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-inlay-type-format ": %s"
"Format string for variable inlays (part of the inlay face)."
:type '(string :tag "String")
:group 'lsp-javascript
:package-version '(lsp-mode . "8.0.1"))

(defface lsp-javascript-inlay-parameter-face
'((t :inherit lsp-javascript-inlay-face))
"Face for inlay parameter hints (e.g. function parameter names at
call-site)."
:group 'lsp-javascript
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-inlay-param-format "%s:"
"Format string for parameter inlays (part of the inlay face)."
:type '(string :tag "String")
:group 'lsp-javascript
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-typescript-surveys-enabled t
"Enabled/disable occasional surveys that help us improve VS
Code's JavaScript and TypeScript support."
:type 'boolean
:package-version '(lsp-mode . "6.1"))

(defcustom lsp-javascript-display-inlay-hints nil
"Whether to display inlay hints."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-enum-member-value-hints nil
"Show inlay hints for enum member values."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-return-type-hints nil
"Show inlay hints for function return types."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-parameter-type-hints nil
"Show inlay hints for function parameters."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-parameter-name-hints "none"
"Level of hinting for parameter types."
:type '(choice (const :tag "none" "none")
(const :tag "literals" "literals")
(const :tag "all" "all"))
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-parameter-name-hints-when-argument-matches-name nil
"Show inlay hints for function parameters even when argument matches
name (e.g. `data' variable passed as `data' parameter)."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-property-declaration-type-hints nil
"Show inlay hints for property declaration types."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(defcustom lsp-javascript-display-variable-type-hints nil
"Show inlay hints for variable types."
:type 'boolean
:package-version '(lsp-mode . "8.0.1"))

(lsp-register-custom-settings
'(("javascript.autoClosingTags" lsp-javascript-auto-closing-tags t)
("javascript.implicitProjectConfig.checkJs" lsp-javascript-implicit-project-config-check-js t)
Expand Down Expand Up @@ -678,7 +754,21 @@ Code's JavaScript and TypeScript support."
("typescript.format.insertSpaceBeforeAndAfterBinaryOperators" lsp-typescript-format-insert-space-before-and-after-binary-operators t)
("typescript.format.insertSpaceBeforeFunctionParenthesis" lsp-typescript-format-insert-space-before-function-parenthesis t)
("typescript.format.placeOpenBraceOnNewLineForControlBlocks" lsp-typescript-format-place-open-brace-on-new-line-for-control-blocks t)
("typescript.format.placeOpenBraceOnNewLineForFunctions" lsp-typescript-format-place-open-brace-on-new-line-for-functions t)))
("typescript.format.placeOpenBraceOnNewLineForFunctions" lsp-typescript-format-place-open-brace-on-new-line-for-functions t)
("typescript.inlayHints.includeInlayEnumMemberValueHints" lsp-javascript-display-enum-member-value-hints t)
("typescript.inlayHints.includeInlayFunctionLikeReturnTypeHints" lsp-javascript-display-return-type-hints t)
("typescript.inlayHints.includeInlayFunctionParameterTypeHints" lsp-javascript-display-parameter-type-hints t)
("typescript.inlayHints.includeInlayParameterNameHints" lsp-javascript-display-parameter-name-hints nil)
("typescript.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName" lsp-javascript-display-parameter-name-hints-when-argument-matches-name t)
("typescript.inlayHints.includeInlayPropertyDeclarationTypeHints" lsp-javascript-display-property-declaration-type-hints t)
("typescript.inlayHints.includeInlayVariableTypeHints" lsp-javascript-display-variable-type-hints t)
("javascript.inlayHints.includeInlayEnumMemberValueHints" lsp-javascript-display-enum-member-value-hints t)
("javascript.inlayHints.includeInlayFunctionLikeReturnTypeHints" lsp-javascript-display-return-type-hints t)
("javascript.inlayHints.includeInlayFunctionParameterTypeHints" lsp-javascript-display-parameter-type-hints t)
("javascript.inlayHints.includeInlayParameterNameHints" lsp-javascript-display-parameter-name-hints nil)
("javascript.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName" lsp-javascript-display-parameter-name-hints-when-argument-matches-name t)
("javascript.inlayHints.includeInlayPropertyDeclarationTypeHints" lsp-javascript-display-property-declaration-type-hints t)
("javascript.inlayHints.includeInlayVariableTypeHints" lsp-javascript-display-variable-type-hints t)))

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

(defun lsp-javascript-update-inlay-hints ()
(if (lsp-javascript-initialized?)
(lsp-request-async
"typescript/inlayHints"
(lsp-make-javascript-inlay-hints-params
:text-document (lsp--text-document-identifier))
(lambda (res)
(lsp--remove-overlays 'lsp-javascript-inlay-hint)
(-each (gethash "inlayHints" res)
#'(lambda (hint)
(-let* (((&javascript:InlayHint :text :position :kind :whitespace-before? :whitespace-after?) hint)
(pos (lsp--position-to-point position))
(overlay (make-overlay pos pos nil 'front-advance 'end-advance)))
(overlay-put overlay 'lsp-javascript-inlay-hint t)
(overlay-put overlay 'before-string
(format "%s%s%s"
(if (and whitespace-before? (not (string= kind lsp/javascript-inlay-hint-kind-type-hint))) " " "")
(propertize (lsp-javascript-format-inlay text kind)
'font-lock-face (lsp-javascript-face-for-inlay kind))
(if whitespace-after? " " ""))))))))
:mode 'tick))

(defun lsp-javascript-format-inlay (text kind)
(cond
((eql kind lsp/javascript-inlay-hint-kind-type-hint) (format lsp-javascript-inlay-type-format text))
((eql kind lsp/javascript-inlay-hint-kind-parameter-hint) (format lsp-javascript-inlay-param-format text))
;; ((eql kind lsp/javascript-inlay-hint-kind-enum-hint) (format lsp-javascript-inlay-enum-format text))
(t text)))

(defun lsp-javascript-face-for-inlay (kind)
(cond
((eql kind lsp/javascript-inlay-hint-kind-type-hint) 'lsp-javascript-inlay-type-face)
((eql kind lsp/javascript-inlay-hint-kind-parameter-hint) 'lsp-javascript-inlay-parameter-face)
(t 'lsp-javascript-inlay-face)))

(defun lsp-javascript-initialized? ()
(when-let ((workspace (lsp-find-workspace 'ts-ls (buffer-file-name))))
(eq 'initialized (lsp--workspace-status workspace))))

(define-minor-mode lsp-javascript-inlay-hints-mode
"Mode for displaying inlay hints."
:lighter nil
(cond
(lsp-javascript-inlay-hints-mode
(lsp-javascript-update-inlay-hints)
(add-hook 'lsp-on-idle-hook #'lsp-javascript-update-inlay-hints nil t))
(t
(lsp--remove-overlays 'lsp-javascript-inlay-hint)
(remove-hook 'lsp-on-idle-hook #'lsp-javascript-update-inlay-hints t))))

(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection (lambda ()
`(,(lsp-package-path 'typescript-language-server)
Expand All @@ -748,6 +888,9 @@ Code's JavaScript and TypeScript support."
(lsp--set-configuration
(ht-merge (lsp-configuration-section "javascript")
(lsp-configuration-section "typescript")))))
:after-open-fn (lambda ()
(when lsp-javascript-display-inlay-hints
(lsp-javascript-inlay-hints-mode)))
:ignore-messages '("readFile .*? requested by TypeScript but content not available")
:server-id 'ts-ls
:request-handlers (ht ("_typescript.rename" #'lsp-javascript--rename))
Expand Down
6 changes: 6 additions & 0 deletions lsp-protocol.el
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,12 @@ See `-let' for a description of the destructuring mechanism."
(rust-analyzer:CommandLink (:title :command) (:arguments :tooltip))
(rust-analyzer:CommandLinkGroup (:commands) (:title)))

(defconst lsp/javascript-inlay-hint-kind-type-hint "Type")
(defconst lsp/javascript-inlay-hint-kind-parameter-hint "Parameter")
(defconst lsp/javascript-inlay-hint-kind-enum-hint "Enum")
(lsp-interface (javascript:InlayHint (:text :position :kind) (:whitespaceBefore :whitespaceAfter))
(javascript:InlayHintsParams (:textDocument) (:range)))

(lsp-interface (clojure-lsp:TestTreeParams (:uri :tree) nil)
(clojure-lsp:TestTreeNode (:name :range :nameRange :kind) (:children)))

Expand Down

0 comments on commit e1e2a49

Please sign in to comment.