Skip to content

Commit 65034e1

Browse files
yyoncholeungbk
andauthored
Automatic installation of eslint language server (#2228)
* Automatic installation of eslint language server - Fixed also handling of `eslint/confirmLocalESLint` - Fixes #1932 - Fixes #1870 * Fix typo: unziped -> unzipped Co-authored-by: Brian Leung <[email protected]>
1 parent 2523987 commit 65034e1

File tree

3 files changed

+91
-9
lines changed

3 files changed

+91
-9
lines changed

clients/lsp-eslint.el

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
:group 'lsp-mode
3737
:link '(url-link "https://github.com/Microsoft/vscode-eslint"))
3838

39+
(defcustom lsp-eslint-unzipped-path (f-join lsp-server-install-dir "eslint/unzipped")
40+
"The path to the file in which `eslint' will be stored."
41+
:type 'file
42+
:group 'lsp-eslint
43+
:package-version '(lsp-mode . "7.1"))
44+
3945
(defcustom lsp-eslint-server-command `("node"
4046
"~/server/out/eslintServer.js"
4147
"--stdio")
@@ -67,6 +73,11 @@
6773
:type '(repeat string)
6874
:package-version '(lsp-mode . "6.3"))
6975

76+
(defcustom lsp-eslint-node "node"
77+
"Path to nodejs."
78+
:type 'file
79+
:package-version '(lsp-mode . "7.1"))
80+
7081
(defcustom lsp-eslint-options nil
7182
"The eslint options object to provide args normally passed to
7283
eslint when executed from a command line (see
@@ -227,16 +238,32 @@ source.fixAll code action."
227238
(when (called-interactively-p 'any)
228239
(lsp--info "source.fixAll.eslint action not available")))))
229240

241+
(defun lsp-eslint-server-command ()
242+
(if (lsp-eslint-server-exists? lsp-eslint-server-command)
243+
lsp-eslint-server-command
244+
`(,lsp-eslint-node ,(f-join lsp-eslint-unzipped-path
245+
"extension/server/out/eslintServer.js")
246+
"--stdio")))
247+
248+
(defun lsp-eslint-server-exists? (eslint-server-command)
249+
(let* ((command-name (f-base (f-filename (cl-first eslint-server-command))))
250+
(first-argument (cl-second eslint-server-command))
251+
(first-argument-exist (and first-argument (file-exists-p first-argument))))
252+
(if (equal command-name lsp-eslint-node)
253+
first-argument-exist
254+
(executable-find (cl-first eslint-server-command)))))
255+
256+
(defun lsp-eslint--confirm-local (_workspace _params)
257+
;; don't bother implementing since it will be dropped in next version of the
258+
;; server
259+
t)
260+
230261
(lsp-register-client
231262
(make-lsp-client
232263
:new-connection
233264
(lsp-stdio-connection
234-
(lambda () lsp-eslint-server-command)
235-
(lambda ()
236-
(let* ((command-name (f-base (f-filename (cl-first lsp-eslint-server-command))))
237-
(first-argument (cl-second lsp-eslint-server-command))
238-
(first-argument-exist (and first-argument (file-exists-p first-argument))))
239-
(if (equal command-name "node") first-argument-exist (executable-find (cl-first lsp-eslint-server-command))))))
265+
(lambda () (lsp-eslint-server-command))
266+
(lambda () (lsp-eslint-server-exists? (lsp-eslint-server-command))))
240267
:activation-fn (lambda (filename &optional _)
241268
(or (string-match-p (rx (one-or-more anything) "."
242269
(or "ts" "js" "jsx" "tsx" "html" "vue"))
@@ -248,7 +275,8 @@ source.fixAll code action."
248275
:multi-root t
249276
:notification-handlers (ht ("eslint/status" #'lsp-eslint-status-handler))
250277
:request-handlers (ht ("workspace/configuration" #'lsp-eslint--configuration)
251-
("eslint/openDoc" 'lsp-eslint--open-doc))
278+
("eslint/openDoc" #'lsp-eslint--open-doc)
279+
("eslint/confirmLocalESLint" #'lsp-eslint--confirm-local))
252280
:server-id 'eslint
253281
:initialized-fn (lambda (workspace)
254282
(with-lsp-workspace workspace
@@ -263,7 +291,20 @@ source.fixAll code action."
263291
,(lsp-make-file-system-watcher
264292
:glob-pattern "**/.eslintignore")
265293
,(lsp-make-file-system-watcher
266-
:glob-pattern "**/package.json")])))))))
294+
:glob-pattern "**/package.json")])))))
295+
:download-server-fn (lambda (_client callback error-callback _update?)
296+
(let ((tmp-zip (make-temp-file "ext" nil ".zip")))
297+
(delete-file tmp-zip)
298+
(lsp-download-install
299+
(lambda (&rest _)
300+
(condition-case err
301+
(progn
302+
(lsp-unzip tmp-zip lsp-eslint-unzipped-path)
303+
(funcall callback))
304+
(error (funcall error-callback err))))
305+
error-callback
306+
:url (lsp-vscode-extension-url "dbaeumer" "vscode-eslint")
307+
:store-path tmp-zip)))))
267308

268309
(provide 'lsp-eslint)
269310
;;; lsp-eslint.el ends here

lsp-mode.el

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7033,6 +7033,46 @@ STORE-PATH to make it executable."
70337033
(set-file-modes store-path #o0700)
70347034
store-path)
70357035
((f-exists? store-path) store-path))))
7036+
7037+
;; unzip
7038+
7039+
(defconst lsp-ext-pwsh-script "powershell -noprofile -noninteractive \
7040+
-nologo -ex bypass Expand-Archive -path '%s' -dest '%s'"
7041+
"Powershell script to unzip file.")
7042+
7043+
(defconst lsp-ext-unzip-script "bash -c 'mkdir -p %2$s && unzip -qq %1$s -d %2$s'"
7044+
"Unzip script to unzip file.")
7045+
7046+
(defcustom lsp-unzip-script (cond ((executable-find "powershell") lsp-ext-pwsh-script)
7047+
((executable-find "unzip") lsp-ext-unzip-script)
7048+
(t nil))
7049+
"The script to unzip."
7050+
:group 'lsp-mode
7051+
:type 'string
7052+
:package-version '(lsp-mode . "7.1"))
7053+
7054+
(defun lsp-unzip (zip-file dest)
7055+
"Get extension from URL and extract to DEST."
7056+
(unless lsp-unzip-script
7057+
(error "Unable to find `unzip' or `powershell' on the path, please customize `lsp-unzip-script'"))
7058+
(shell-command (format lsp-unzip-script zip-file dest)))
7059+
7060+
7061+
;; VSCode marketplace
7062+
7063+
(defcustom lsp-vscode-ext-url
7064+
"https://marketplace.visualstudio.com/_apis/public/gallery/publishers/%s/vsextensions/%s/%s/vspackage"
7065+
"Vscode extension template url."
7066+
:group 'lsp-mode
7067+
:type 'string
7068+
:package-version '(lsp-mode . "7.1"))
7069+
7070+
(defun lsp-vscode-extension-url (publisher name &optional version)
7071+
"Return the URL to vscode extension.
7072+
PUBLISHER is the extension publisher.
7073+
NAME is the name of the extension.
7074+
VERSION is the version of the extension, defaults to `latest'"
7075+
(format lsp-vscode-ext-url publisher name (or version "latest")))
70367076

70377077

70387078

lsp-protocol.el

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ See `-let' for a description of the destructuring mechanism."
261261
(lsp-get ,source ,key)))
262262

263263
(lsp-interface (eslint:StatusParams (:state) nil)
264-
(eslint:OpenESLintDocParams (:url) nil))
264+
(eslint:OpenESLintDocParams (:url) nil)
265+
(eslint:ConfirmESLintLibraryParams (:scope :file :libraryPath) nil))
265266

266267
(lsp-interface (haxe:ProcessStartNotification (:title) nil))
267268

0 commit comments

Comments
 (0)